Java - 动态 class 加载程序的奇怪行为
Java - Strange behaviour with dynamic class loader
在我的代码中,我想从 Jar 文件动态加载模块 class 实现。
在我的目录中有 3 个文件:A.jar、B.jar、C.jar
每个 jar 都有一个名为 Main 的 class,它扩展了 Module class
A.jar 代码示例:
public class Main extends Module {
private static String name = "A";
public Main() {
super(name);
}
}
(B 和 C 文件相同,但名称 属性 中使用 "B" 和 "C" 而不是 "A"。
我的模块class代码是:
public abstract class Module{
private StringProperty nameProperty;
public Module(String name){
this.nameProperty = new SimpleStringProperty(name);
}
public StringProperty nameProperty(){
return nameProperty;
}
}
这是我用来动态加载三个 classes 的代码:
for (File moduleFile : Data.modulesDir.listFiles()) {
try {
URL url = moduleFile.toURI().toURL();
Class[] parameters = new Class[] { URL.class };
URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<URLClassLoader> sysClass = URLClassLoader.class;
Method method = sysClass.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke(sysLoader, new Object[] { url });
Constructor<?> cs = ClassLoader.getSystemClassLoader().loadClass("com.ehzlab.webreaper.module.Main")
.getConstructor();
Module instance = (Module) cs.newInstance();
System.out.println(instance.nameProperty.get());
} catch (Exception e) {
e.printStackTrace();
}
}
我期待这个输出:
A
B
C
但我得到的是这个:
A
A
A
似乎在每次文件列表迭代时加载相同的 jar。但是调试我注意到 URL 每次都会改变。
我也试过倒序,比如把B.jar放在另一个jar前面,结果是:
B
B
B
为什么?
只是因为你每次都使用相同的类加载器,它不会重新加载底层 类:
ClassLoader.getSystemClassLoader()...
为了访问特定的 类,您必须使用适当的类加载器来加载特定的 jar
文件(可能是 sysLoader
,不确定,因为我没检查):
Constructor<?> cs = sysLoader.loadClass("com.ehzlab.webreaper.module.Main")
.getConstructor();
也看看这个问题:How should I load Jars dynamically at runtime?
在我的代码中,我想从 Jar 文件动态加载模块 class 实现。
在我的目录中有 3 个文件:A.jar、B.jar、C.jar 每个 jar 都有一个名为 Main 的 class,它扩展了 Module class
A.jar 代码示例:
public class Main extends Module {
private static String name = "A";
public Main() {
super(name);
}
}
(B 和 C 文件相同,但名称 属性 中使用 "B" 和 "C" 而不是 "A"。
我的模块class代码是:
public abstract class Module{
private StringProperty nameProperty;
public Module(String name){
this.nameProperty = new SimpleStringProperty(name);
}
public StringProperty nameProperty(){
return nameProperty;
}
}
这是我用来动态加载三个 classes 的代码:
for (File moduleFile : Data.modulesDir.listFiles()) {
try {
URL url = moduleFile.toURI().toURL();
Class[] parameters = new Class[] { URL.class };
URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<URLClassLoader> sysClass = URLClassLoader.class;
Method method = sysClass.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke(sysLoader, new Object[] { url });
Constructor<?> cs = ClassLoader.getSystemClassLoader().loadClass("com.ehzlab.webreaper.module.Main")
.getConstructor();
Module instance = (Module) cs.newInstance();
System.out.println(instance.nameProperty.get());
} catch (Exception e) {
e.printStackTrace();
}
}
我期待这个输出:
A
B
C
但我得到的是这个:
A
A
A
似乎在每次文件列表迭代时加载相同的 jar。但是调试我注意到 URL 每次都会改变。 我也试过倒序,比如把B.jar放在另一个jar前面,结果是:
B
B
B
为什么?
只是因为你每次都使用相同的类加载器,它不会重新加载底层 类:
ClassLoader.getSystemClassLoader()...
为了访问特定的 类,您必须使用适当的类加载器来加载特定的 jar
文件(可能是 sysLoader
,不确定,因为我没检查):
Constructor<?> cs = sysLoader.loadClass("com.ehzlab.webreaper.module.Main")
.getConstructor();
也看看这个问题:How should I load Jars dynamically at runtime?