繁体   English   中英

为什么此URLClassLoader有时起作用而有时却不起作用?

[英]Why this URLClassLoader sometimes works and sometimes doesn't?

我有一个非常复杂的Java软件,该软件必须动态加载类,创建对象并调用其方法之一。 事实证明,在某些情况下,如果加载的类引用了另一个类,则会引发NoClassDefFoundError (由ClassNotFoundException引起)。

说我们有:

public interface Go {
    void go();
}

说要加载的类是:

package foo;
import static baz.Baz.BAZ;
public class Foo implements Go {
    @Override
    void go() { 
        ...
        something = BAZ;
        ...
    }
}

哪里

package baz;
public class Baz {
    public static final int BAZ = 111;
    ...
}

假设以这种方式加载类:

try (final URLClassLoader loader = new URLClassLoader(new URL[] { url })) {
    final Class<? extends Foo> clazz =  
        loader.loadClass("foo.Foo").asSubclass(Go.class);
    this.obj = clazz.newInstance();
    this.obj.go();
} catch ...

然后一切正常。 假设您改为通过其他方式进行操作:

try (final URLClassLoader loader = new URLClassLoader(new URL[] { url })) {
    final Class<? extends Foo> clazz =  
        loader.loadClass("foo.Foo").asSubclass(Go.class);
    this.obj = clazz.newInstance();
    //we do not invoke go() now...
} catch ...

//later, in another method...
this.obj.go();

现在,调用go()会引发NoClassDefFoundError ,抱怨它无法加载baz.Baz 当然,URL是相同的。 当然foo.Foobaz.Baz都在url指示的路径中。 我可以看到的唯一区别是调用go()方法的时刻。

怎么了

怎么了

我认为问题是这样的:

try (final URLClassLoader loader = new URLClassLoader(new URL[] { url })) {

这将导致在退出try块时关闭类加载器。 close()方法的javadoc说:

关闭此URLClassLoader,以使其不再可用于加载此加载器定义的新类或资源。

调用go()方法将触发Go类的类初始化,这就是导致Baz类被加载和初始化的原因。 如果在关闭类加载器之后发生后一个类加载,则它将失败。

如果一个类依赖于其他类,则它们会延迟加载

这意味着加载foo.FOO不会同时加载baz.BAZ 后者是在首次访问时加载的。 在您的情况下,对go()的方法调用也会加载它。

在第二个示例中,在调用go()方法时, URLClassLoader关闭 -通过try-with-resources语句。 因此,它无法再加载类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM