Java - 动态类加载器的奇怪行为

时间:2016-12-21 15:55:27

标签: java jar classloader

在我的代码中,我想从Jar文件中动态加载Module类实现。

在我的目录中,我有3个文件:A.jar,B.jar,C.jar 每个jar都有一个名为Main的类,它扩展了Module类

A.jar代码示例:

public class Main extends Module {

    private static String name = "A";

    public Main() {
        super(name);
    }

}

(B和C文件相同,但在名称属性中使用“B”和“C”代替“A”。)

我的模块类代码是:

public abstract class Module{

    private StringProperty nameProperty;

    public Module(String name){
        this.nameProperty = new SimpleStringProperty(name);
    }

    public StringProperty nameProperty(){
         return nameProperty;
     }

}

这是我用来动态加载这三个类的代码:

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

为什么?

1 个答案:

答案 0 :(得分:0)

只是因为您每次都使用相同的类加载器,而不会重新加载基础类:

ClassLoader.getSystemClassLoader()...

为了访问特定的类,您必须使用适当的类加载器来加载特定的jar文件(可能是sysLoader,不确定,因为我没有检查):

Constructor<?> cs = sysLoader.loadClass("com.ehzlab.webreaper.module.Main")
                    .getConstructor();

同样看看这个问题:How should I load Jars dynamically at runtime?