我有一个小程序,试图允许通过类文件复制到特定的插件 ext
目录。
该程序源于https://javaranch.com/journal/200607/plugins.html 我试图简化它,并添加一个目录扫描功能来扫描原始代码缺少的包和目录。
当运行原始代码时,它可以工作。当我添加目录和包扫描功能并在演示包上进行测试时,它失败了。以下是样本。
接受动态加载的类文件作为插件的系统的目录布局:
testpack-+
|
+---PluginDemo.java
|
+---PluginFunction.java
测试插件的目录布局:
b-+
|
+---Fibonacci.java
testpack-+
|
+---PluginFunction.java
这个 PluginDemo
使用自定义类加载器的代码:
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, 0, 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)
我需要帮助让这个包和目录扫描功能类加载器工作。谢谢。
1条答案
按热度按时间u5rb5r591#
查看错误和方法classloader.defineclass,我认为name参数必须
.
作为包分隔符,而不是/
或者\
.在getplugins的代码中,子文件是使用file.separator构造的