1

我有一个Foo实现IDoMagic接口的类。该类Foo由系统类加载器加载,IDoMagic接口在第三方组件中定义,我认为它将接口加载到另一个类加载器(动态类加载器)中。

当我尝试创建 的新实例时Foo,我得到了NoClassDefFoundfor IDoMagic。我认为这是因为它是由不同的类加载器加载的。

我试图创建一个BridgeClassLoader(类似于 Guice 使用的),然后Foo从系统类加载器加载类,并从不同的类加载器加载所有其他类,我认为这是用于IDoMagic但没有任何成功的类加载器。

有办法解决吗?

4

1 回答 1

0

Java 中的类加载器 (CL) 使用委托策略,这意味着 CL 首先会询问她的父级,后者也会询问她的父级,她是否知道类 X 的定义。只有当父级、任何祖先或当前类加载器知道 X 的类定义,然后当前类加载器将从相应X.class文件加载定义。

如果一个类Foo由系统类加载器加载,则任何Foo依赖的类也需要由系统 CL 或该 CL 的父级加载。正如IDoMagic其他 JAR 中提供的那样,您很可能需要将此 JAR 文件添加到类路径(java -cp ...java -jar ...)中。由于委托模型,作为此 CL 的(大等)子级的任何 CL 也将获得对任何父级 CL 加载的类定义的访问权限。

如果IDoMagic需要由自定义 CLFoo加载,则不得由系统 CL 加载,而是使用自定义 CL 或此 CL 的子级加载,以便委托策略启动并提供IDoMagicifFoo已加载/实例化的定义。

有一个自定义委托 CL 模型,其中共享类保存在一种公共 CL 列表/数组中,可以由依赖 CL 使用。依赖类不是公共 CL 的直接子类,而是委托 CL 的子类,委托 CL 只是在询问父类是否没有一个子类能够执行任务之前将调用委托给公共类。这里的一个解决方案可能是这样的结构:

bootstrap CL
- system CL
  - delegation CL
    - common CL
    - plugin CL
      - plugin 1 CL
      - plugin 2 CL

在这里,委托 CL 需要将调用委托loadClass(...)findClass(...)它所包含的公共 CL(对象组合),并且只有当它找不到定义时,才将调用委托给其父级。类似于这个仍然是实验课

此委托加载器可以IDoMagic使用公共 CL fe 和Foo具有插件加载器之一的类加载,该插件加载器不是common CL. 但是,这要求delegation CL在询问父级之前先对公共 CL 进行所有调用。此外,这个委托加载器给表带来了一些开销,因为它使自定义 CL 的优点之一(卸载未使用的类)更加困难。

于 2016-04-11T14:07:06.743 回答