Как выгрузить уже загруженный класс в Java?

Как выгрузить класс из загрузчика классов, чтобы я мог использовать недавно измененный класс "на лету" без перезагрузки моего приложения (горячее развертывание)? Возможно ли это сделать?

Ответы

Ответ 1

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

Ответ 2

Вы не можете выгрузить класс, который фактически используется. Но вы можете захотеть взглянуть на такие платформы, как OSGi, если вы хотите перезагрузить или переустановить приложение во время выполнения.

Ответ 3

Вы не можете явно выгрузить класс.

В принципе, вы можете принудительно перезагрузить класс через Classloader.loadClass(). С этого момента все новые экземпляры этого класса будут использовать новое определение.

В любом случае, я буду действовать с особой осторожностью...

Ответ 4

Вам нужно будет создать пользовательский ClassLoader: который возвращает все Object, завернутые внутри прокси. ClassLoader должен иметь список всех ссылочных прокси (сохраните этот список WeakReference d). Если вы решите "разгрузить" и, таким образом, "перезагрузить" любой класс, вы ждете до загрузки класса, найдите все прокси в списке и замените фактический объект.

Есть несколько проблем: вам нужно Reflection, чтобы получить все частные переменные и reset внутреннее состояние (см. setAccesible on Field). Также могут возникнуть проблемы многопоточности, поэтому прокси-сервер должен быть синхронизирован: это делает работу плохой.

Вы можете лучше искать решение Google Guice, которое позволяет отключать и перезагружать модули во время выполнения. Это может быть решением, но слишком раздутым для небольшого приложения. Тем не менее: я не уверен, что GC также выгружает неиспользуемые классы.