【问题标题】:Why this URLClassLoader sometimes works and sometimes doesn't?为什么这个 URLClassLoader 有时有效,有时无效?
【发布时间】:2016-06-24 23:26:50
【问题描述】:

我有一个相当复杂的 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。当然,网址是一样的。当然foo.Foobaz.Baz 都在url 指示的路径中。我能看到的唯一区别是调用go() 方法的那一刻。

这里有什么问题?

【问题讨论】:

  • 缺少一些信息:Go 在哪个包中?传递给 URLClassloader 的 URL 是什么?编译器是否接受 Foo 作为子类 Go 的加载,然后将其分配给 ? extends Foo

标签: java classloader urlclassloader


【解决方案1】:

这里有什么问题?

我认为问题是这样的:

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

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

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

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

【讨论】:

    【解决方案2】:

    如果一个类依赖于其他类,这些是延迟加载的

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

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

    【讨论】:

      猜你喜欢
      • 2019-09-18
      • 1970-01-01
      • 2010-10-24
      • 2019-05-30
      • 2018-06-15
      • 2011-02-13
      • 1970-01-01
      • 1970-01-01
      • 2019-01-03
      相关资源
      最近更新 更多