java 从另一个类装入器装入带有接口的类

xeufq47z  于 2023-01-29  发布在  Java
关注(0)|答案(2)|浏览(117)

我有一个类Foo,它实现了一个IDoMagic接口,Foo类是由系统类加载器加载的,IDoMagic接口是在第三方组件中定义的,我认为该组件在另一个类加载器(动态类加载器)中加载该接口。
当我尝试创建一个Foo的新示例时,得到的是IDoMagicNoClassDefFound,我认为这是因为它是由另一个类加载器加载的。
我尝试创建一个BridgeClassLoader(类似于Guice使用的BridgeClassLoader),然后从系统类加载器加载Foo类,并从另一个不同的类加载器加载所有其他类,我认为这是用于IDoMagic的类加载器,但没有任何成功。
有什么办法吗?

u5i3ibmn

u5i3ibmn1#

Java中的类加载器(CL)采用委托策略,这意味着CL首先会询问她的父类,父类也会询问她的父类,如果她知道类X的定义。只有当父类、祖先类或当前类加载器都不知道X的类定义时,当前类加载器才会从相应的X.class文件中加载定义。
如果Foo类是由系统类加载器加载的,那么Foo所依赖的任何类也需要由系统CL或该CL的父类加载。由于IDoMagic是在另一个JAR中提供的,所以您很可能需要将该JAR文件添加到类路径(java -cp ...java -jar ...)中。等等)该CL的子CL也将获得对由任何父CL加载的类定义的访问。
如果IDoMagic需要由自定义CL加载,则Foo不能由系统CL加载,而是必须与自定义CL或该CL的子CL一起加载,以便在加载/示例化Foo的情况下,委托策略启动并提供IDoMagic的定义。
有一个定制的委托CL模型,其中共享类被保存在一种公共CL列表/数组中,该公共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(对象组合),并且只有在找不到定义时才将调用委托给其父级。
此委托加载器允许使用公共CL加载IDoMagic,并使用其中一个插件加载器加载Foo类,该插件加载器不是common CL的直接子级。但是,这要求delegation CL在请求父级之前首先将所有调用传播到公共CL。此外,这个委托加载器给表带来了一些开销,因为它使得定制CL的优点之一(卸载未使用的类)更加困难。

wn9m85ua

wn9m85ua2#

如果类装入器接收到类装入请求,它不会自装入
相反,请求被委托给父类的装入器,如果父类装入器仍然有自己的父类装入器,则进一步请求
请求最终会到达顶层启动类加载器,如果父类加载器能够完成类加载任务,则会成功返回
如果父加载程序无法完成加载任务,子加载程序将尝试自己加载,这就是双亲委托模型。

相关问题