Как динамически загрузить класс Java без использования загрузчика классов?


Я недавно видел онлайн-презентацию JRebel, в которой они объясняют, что делает их продукт, в одном из слайдов они упоминают, что не используют загрузчики классов (см. скриншот ниже).

У меня есть несколько проектов, в которых я использую загрузчики классов для динамической загрузки классов во время выполнения, например для внедрения зависимостей (например, в разработанной мной платформе Maker Factory). Я думал, что единственный способ загрузить класс в Java - это использовать загрузчик классов.

Введите описание изображения здесь

6 5

6 ответов:

Отказ от ответственности: я занимаюсь разработкой JRebel

Технически, можно обойти загрузчик классов с некоторой небезопасной магией, и JVM использует это с помощью лямбд при создании анонимных классов среды выполнения (в Java 8).

Однако JRebel фактически интегрируется с существующими загрузчиками классов и не создает новых-вот что означает слайд. JRebel не сбрасывает существующий загрузчик классов, когда он должен перезагрузить класс. Вместо этого он загружает и версирует классы внутри существующих загрузчиков классов.

Они не используют никаких новых загрузчиков классов; они расширяют стандартные.

Http://zeroturnaround.com/software/jrebel/learn/faq/#how_does_jrebel_work

Они упоминают, что не используют загрузчики классов.

Каждый класс использует загрузчик классов (кроме примитивов). Однако библиотека не должна создавать дополнительный загрузчик классов.

Даже программа "Hello World" будет иметь два загрузчика классов (один для boostrapping)

Я думал, что единственный способ загрузить класс в Java-это использовать загрузчик классов.

Это так, но вы можете заставить существующий загрузчик классов загрузить ваш класс, который является hack, но может быть простой в эксплуатации.

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

Таким образом, ответ на этот вопрос может быть следующим: невозможно динамически загрузить класс Java без использования загрузчика классов в первый раз. Но можно частично перезагрузить класс, используя загрузчик классов.

Основываясь на ссылке ответа Дэйва Ньютона, извлекая важные вещи из JRebel faq:

Они используют Instrumentation API для инструментирования загрузчиков классов контейнеров / серверов, таким образом, они могут динамически контролировать и управлять процесс загрузки. Они будут сканировать путь к классу в поисках.файл класса, соответствующий загруженному классу, и используйте метку времени файла для обнаружения изменений в нем. Когда изменение обнаружено, они будут распространять это изменение через инструментальный загрузчик классов. Он сохранит существующие экземпляры класса, но не будет повторно запускать конструктор, что означает, что новые добавленные поля не будут инициализированы.

Действительно, единственный способ загрузить класс - это через загрузчик классов.

Люди из JRebel, вероятно, хотели сказать, что не используют загрузчики классов для переопределения классов. Переопределение класса возможно другими способами, например через JVMTI.

Вы, конечно, можете сами прочитать файл класса в память. Но чтобы сделать класс доступным в коде, вам все равно нужно использовать ClassLoader#defineClass.

В общем случае любой класс, используемый в программе, должен быть определен загрузчиком классов, иначе что должно возвращать getClass().getClassLoader()?