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?