简体   繁体   中英

Custom Java classloader and inner classes

I have this method (in my own classloader) that loads classes from zip:

ZipInputStream in = new ZipInputStream(new FileInputStream(zip));
ZipEntry entry;
while ((entry = in.getNextEntry()) != null) {
    if (!entry.isDirectory()) {
        byte[] buffer = new byte[(int) entry.getSize()];
        in.read(buffer);
        if (!entry.getName().endsWith(".class"))
            continue;
        String name = entry.getName().replace(".class", "").replace("/", ".");
        Class<?> cls = this.defineClass(name, buffer, 0, buffer.length);
        this.resolveClass(cls);
    }
}

The zip that im trying to load looks like this:

TestClass.class
TestClass$SomeOtherInnerClass.class 

My problem is that defineClass() fails to load the TestClass$SomeOtherInnerClass. If this class is loaded before the actual TestClass i get this:

java.lang.NoClassDefFoundError: TestClass

I also tried to load the TestClass.class first but then im getting this error:

java.lang.ClassFormatError: Wrong InnerClasses attribute length in class file TestClass 

Is there something i'm doing wrong?

I looks like you may not be overriding ClassLoader.findClass() . Without doing that, the ClassLoader you are extending does not know how to find these classes.

Override that function with something that simply looks up in a private static Map<String, Class<?>> for the class. As you load each class, put it into that map.

The difficulty will be in loading classes in the correct order, as your current implementation will not allow you to jump back to searching the Zip and calling defineClass() from your new findClass() method.

至少有一个错误,你没有(必然)完全读取缓冲区(并且ZipEntry.getSize可能返回-1 )。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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