如何解决从包类加载产生NoClassDefFoundError
我有一个小程序,试图通过复制到特定ext
目录的类文件允许插件。
该程序派生自https://javaranch.com/journal/200607/Plugins.html,我曾尝试对其进行简化,并增加了目录扫描功能,以扫描原始代码缺乏的软件包和目录。
运行原始代码时,它可以工作。当我添加目录和程序包扫描功能并在演示程序包上对其进行测试时,它将失败。下面是示例。
testpack-+
|
+---PluginDemo.java
|
+---PluginFunction.java
测试插件的目录布局:
b-+
|
+---Fibonacci.java
testpack-+
|
+---PluginFunction.java
package testpack;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.*;
public class PluginDemo extends ClassLoader {
static String pluginsDir = "ext";
static File basePluginDir = null;
File directory;
static List plugins;
public static void main(String args[]) {
PluginDemo demo = new PluginDemo();
basePluginDir = new File(System.getProperty("user.dir") + File.separator + pluginsDir);
demo.getPlugins(pluginsDir,"");
}
PluginDemo() {
plugins = new ArrayList();
}
protected void getPlugins(String directory,String parent) {
File dir = new File(System.getProperty("user.dir") + File.separator + directory);
if (dir.exists() && dir.isDirectory()) {
String[] files = dir.list();
for (int i = 0; i < files.length; i++) {
try {
// Allows recursive targetting of nested directories
String newTargetFile = System.getProperty("user.dir") + File.separator + directory + File.separator
+ files[i];
System.out.println("Targetting: " + newTargetFile);
File currentTarget = new File(newTargetFile);
if (currentTarget.isDirectory()) {
String newDirectoryTarget = directory + File.separator + files[i];
getPlugins(newDirectoryTarget,files[i]);
}
if (!files[i].endsWith(".class"))
continue;
String childFile = parent + File.separator + files[i].substring(0,files[i].indexOf("."));
Class c = loadClass(childFile);
Class[] intf = c.getInterfaces();
for (int j = 0; j < intf.length; j++) {
if (intf[j].getName().equals("PluginFunction")) {
PluginFunction pf = (PluginFunction) c.newInstance();
plugins.add(pf);
continue;
}
}
} catch (Exception ex) {
System.err.println("File " + files[i] + " does not contain a valid PluginFunction class.");
ex.printstacktrace();
}
}
}
}
public Class loadClass(String name) throws ClassNotFoundException {
return loadClass(name,true);
}
public Class loadClass(String classname,boolean resolve) throws ClassNotFoundException {
try {
Class c = findLoadedClass(classname);
if (c == null) {
try {
c = findSystemClass(classname);
} catch (Exception ex) {
}
}
if (c == null) {
String filename = classname.replace('.',File.separatorChar) + ".class";
// Create a File object. Interpret the filename relative to the
// directory specified for this ClassLoader.
File baseDir = new File(System.getProperty("user.dir"));
File f = new File(baseDir,PluginDemo.pluginsDir + File.separator + filename);
int length = (int) f.length();
byte[] classbytes = new byte[length];
DataInputStream in = new DataInputStream(new FileInputStream(f));
in.readFully(classbytes);
in.close();
c = defineClass(classname,classbytes,length);
}
if (resolve)
resolveClass(c);
return c;
} catch (Exception ex) {
throw new ClassNotFoundException(ex.toString());
}
}
}
PluginFunction
界面代码:
package testpack;
public interface PluginFunction {
// let the application pass in a parameter
public void setParameter (int param);
// retrieve a result from the plugin
public int getResult();
// return the name of this plugin
public String getPluginName();
// can be called to determine whether the plugin
// aborted execution due to an error condition
public boolean hasError();
}
Fibonacci.java
代码:
package b;
import testpack.PluginFunction;
public class Fibonacci implements PluginFunction {
int parameter = 0;
boolean hasError = false;
public boolean hasError() {
return hasError;
}
public void setParameter (int param) {
parameter = param;
}
public int getResult() {
hasError = false;
return fib(parameter);
}
protected int fib (int n) {
if (n < 0) {
hasError = true;
return 0;
}
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return fib(n-1) + fib(n-2);
}
public String getPluginName() {
return "Fibonacci";
}
}
Targetting: C:\Users\Administrator\eclipse-workspace\TestPluginSystem\ext\b\Fibonacci.class
Exception in thread "main" java.lang.NoClassDefFoundError: b\Fibonacci (wrong name: b/Fibonacci)
at java.lang.classLoader.defineClass1(Native Method)
at java.lang.classLoader.defineClass(ClassLoader.java:760)
at java.lang.classLoader.defineClass(ClassLoader.java:642)
at testpack.PluginDemo.loadClass(PluginDemo.java:89)
at testpack.PluginDemo.loadClass(PluginDemo.java:65)
at testpack.PluginDemo.getPlugins(PluginDemo.java:47)
at testpack.PluginDemo.getPlugins(PluginDemo.java:40)
at testpack.PluginDemo.main(PluginDemo.java:19)
我需要帮助来使此程序包和具有目录扫描功能的类加载器正常工作。谢谢。
解决方法
考虑错误和方法ClassLoader.defineClass,我认为name参数必须以.
作为包分隔符,而不是/
或\
。
在您的getPlugins代码中,childFile是使用File.separator构造的
String childFile = parent + File.separator + files[i].substring(0,files[i].indexOf("."));
Class c = loadClass(childFile);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。