课程:
public interface Inter {
...some methods...
}
public class Impl implements Inter {
...some implementations...
}
问题在于,出于某种原因,我必须使用子 ClassLoader加载接口Inter
,并使用 parent Impl > ClassLoader。
在这种情况下,我将获得NoClassDefError
,因为尝试加载实现Impl
的父ClassLoader不知道子类ClassLoader中加载的接口Inter
。
有没有办法用子ClassLoader(context ClassLoader)加载实现?或者我可能需要编写一些自定义的ClassLoader来加载它们(通过破坏委托规则)?
答案 0 :(得分:3)
问题是对于一些怪异的人 原因,我必须加载界面 与孩子ClassLoader和 实现类Impl与父级 类加载器。
我无法理解为什么子类加载器必须加载接口,同时让父类加载器加载实现。这肯定会造成麻烦,因为在JVM使用的类加载机制中没有机制来将类加载到子类加载器。在JVM中实现类加载行为的常用机制在ClassLoader类的API文档中定义:
ClassLoader类使用a 委托模型来搜索类 和资源。每个实例 ClassLoader具有关联的父级 类加载器。当要求找到一个 类或资源,ClassLoader 实例将委托搜索 其父级的类或资源 尝试查找之前的类加载器 类或资源本身。该 虚拟机的内置类 loader,称为“bootstrap类 loader“,本身并没有父母 但可以作为一个的父母 ClassLoader实例。
可以通过扩展ClassLoader class并覆盖loadClass() method来编写自定义类加载器。扩展此方法允许您以两种方式之一更改类加载委派:
大多数类加载器都是作为父级优先级的类加载器实现的。这是因为委托机制能够向上移动树而不是向下移动。
如果您真的希望将类的加载和查找委托给层次结构中的子类加载器,则必须在父类的自定义类加载器中管理对它们的引用。这并不容易,并且除了非常特殊的情况之外通常都没有完成,因为它很容易以可怕的ClassNotFoundException和NoClassDefFoundError结束,因为必须小心只从子类加载器加载所需的类,而其余必须总是被推迟到父级(除非我弄错了,某些Java EE容器中的共享库的功能是以这种方式实现的。)
话虽如此,理想的解决方案是尝试在父类加载器中加载接口和实现类,并依赖委托机制来确保类对两个类加载器都可见;父母可以“看到”自己加载的类,孩子可以“看到”父母的类。
PS:加载和定义类时不要忘记使用AccessController.doPrivileged。
答案 1 :(得分:0)
你是否覆盖了java.lang.ClassLoader的loadClass(String name,boolean resolve)?
我邀请你做过。
加载的默认行为首先加载父类文件,并将其标记为已加载的文件,如果找到,loadClass将首先获取加载的类,这是我重写的guest用户的方式,并且没有在自定义的类加载器中调用super.loadClass方法