[英]How to load classes from jar file in correct order
我编写了一个Java类加载器来从jar文件加载类。
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry element = entries.nextElement();
if (element.getName().endsWith(".class")) {
//Class Manipulation via ASM
//Loading class with MyClassloader
}
}
问题是:当我加载一个类,从同一个Jar中的一个类中的Sublcass并且子类尚未加载时,我得到一个ClassNotFoundException。
例:
class A extends B{}
Class B{}
由于按字母顺序排列,首先加载A类。 我得到了类B的ClassNotFoundException。此时,未加载B类。
我假设您的类加载是作为某种推送类文件执行的。 不过你应该拉它们。 为了解释我的意思,让我们看一下普通Java类加载的简短示例:
class Main {
public static void main(String[] args) {
new B();
}
}
class B extends A { }
class A { }
在创建new B()
, Main
的类加载器基本上执行classLoader.loadClass("B")
。 此时, B
的超级A
尚未加载。 同时,类加载器不能知道B
有A
作为它的超类。 因此,类加载器通过在完成B
的类加载之前询问自己的classLoader.loadClass("A")
来负责加载类。
让我们假设类加载器不知道A
或B
但它有一个方法来显式加载由classLoader.inject(String, byte[])
接收的外部实体的类。 然后这个调用序列不会计算:
classLoader.inject("B", bBytes);
classLoader.inject("A", aBytes);
因为在加载B
,类加载器还不知道A
实现自己的类加载器时需要做的是将类存储在某种映射中,并实现类加载器的类加载方法,如:
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = map.get(name);
if (bytes != null) {
return defineClass(name, bytes, 0, bytes.length);
} else {
throw new ClassNotFoundException(name);
}
}
通过允许类加载器确定加载顺序,您可以完全避免这个问题。
更准确地说,你需要在两个步骤中进行操作和加载,其中伪算法看起来像这样:
Enumeration<JarEntry> entries = jarFile.entries();
MyClassLoader classLoader = new MyClassLoader();
// First we generate ALL classes that the class loader is supposed to load.
// We then make these classes accessible to the class loader.
while (entries.hasMoreElements()) {
JarEntry element = entries.nextElement();
if (element.getName().endsWith(".class")) {
// Class Manipulation via ASM
classLoader.addClass( ... );
}
}
// Now that the class loader knows about all classes that are to be loaded
// we trigger the loading process. That way, the class loader can query
// itself about ANY class that it should know.
while (entries.hasMoreElements()) {
JarEntry element = entries.nextElement();
if (element.getName().endsWith(".class")) {
classLoader.loadClass( ... );
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.