Использование ClassLoader.defineClassCond для получения объекта класса из байтов класса, созданного с помощью ASM, исключение NoClassDefFoundException?

#java #class #assembly #noclassdeffounderror

#java #класс #сборка #noclassdeffounderror

Вопрос:

Я сгенерировал класс, взяв байты базового класса и приняв их через пользовательский адаптер класса. Когда я вызываю define class для байтов, созданных как произведение базового класса, я получаю эту ошибку:

 Caused by: java.lang.NoClassDefFoundError: com/example/MyClassBase
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(Unknown Source)
    ... 24 more
Caused by: java.lang.ClassNotFoundException: com.example.MyClassBase
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 26 more
  

Базовый класс был загружен URLClassLoader из jar. Существует ли какой-либо базовый вызов метода в defineClass, который вызывает исключение, поскольку он не может найти загруженный класс? Как я могу это исправить?

Имейте в виду, что загружать базовый класс другим способом будет непрактично. В качестве параметра проблемы я бы сказал, предположим, что он должен быть загружен через URLClassLoader из другого jar.

Ответ №1:

Я думаю, вы пытаетесь загрузить модифицированный байт-код, который полагается на com.example.MyClassBase через ClassLoader, который не может видеть этот класс. Когда вы создаете свой собственный экземпляр ClassLoader для загрузки измененного класса, вы должны связать его с существующим ClassLoader, используя его конструктор для установления родительской / дочерней иерархии загрузчиков, что помогает избежать именно этой проблемы.

Комментарии:

1. Проблема в том, что это не «мой» загрузчик классов, и я не вижу практического (или простого) способа изменить способ создания загрузчика классов, который загружает базовый класс, или как он загружает базовый класс. Если бы я должен был определить новый класс с помощью ClassLoader, который загрузил базовый класс, мне бы повезло больше?

2. Подтверждено, определение класса с помощью ClassLoader, который загружал базовый класс, исправило исключение ClassNotFoundException и, следовательно, ошибку NoClassDefFoundError . Я не знаю, точно ли это то, на что вы намекали в своем ответе, но именно ваш ответ заставил меня попытаться это сделать, поэтому для этого я отмечу его как правильный!

3. Я не был уверен, что полностью понял вашу ситуацию, но я думаю, что вы сказали то, что я имел в виду 🙂 Я рад, что это помогло, так или иначе.