Пользовательский загрузчик классов Java и внутренние классы - PullRequest
3 голосов
/ 25 марта 2011

У меня есть этот метод (в моем собственном загрузчике классов), который загружает классы из 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);
    }
}

ZIP, который я пытаюсь загрузить, выглядит следующим образом:

TestClass.class
TestClass$SomeOtherInnerClass.class 

Моя проблемаявляется то, что defineClass () не может загрузить TestClass $ SomeOtherInnerClass.Если этот класс загружается до фактического TestClass, я получаю это:

java.lang.NoClassDefFoundError: TestClass

Я также пытался сначала загрузить TestClass.class, но затем я получаю эту ошибку:

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

Есть личто-то я делаю не так?

Ответы [ 2 ]

3 голосов
/ 25 марта 2011

Похоже, вы не можете переопределить ClassLoader.findClass(). Без этого ClassLoader, который вы расширяете, не знает, как найти эти классы.

Переопределите эту функцию чем-то, что просто ищет в private static Map<String, Class<?>> для класса. Когда вы загружаете каждый класс, поместите его в эту карту.

Трудность будет заключаться в загрузке классов в правильном порядке, поскольку ваша текущая реализация не позволит вам вернуться к поиску Zip и вызову defineClass() из вашего нового findClass() метода.

0 голосов
/ 25 марта 2011

Есть по крайней мере одна ошибка, из-за которой вы (не обязательно) не полностью читаете буфер (и ZipEntry.getSize может вернуть -1).

...