繁体   English   中英

如何以正确的顺序从jar文件加载类

[英]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尚未加载。 同时,类加载器不能知道BA作为它的超类。 因此,类加载器通过在完成B的类加载之前询问自己的classLoader.loadClass("A")来负责加载类。

让我们假设类加载器不知道AB但它有一个方法来显式加载由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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM