Tomcat: как Tomcat самостоятельно выгружает классы?
Я ищу способ заменить банку со старой функциональностью на новую, не останавливая все приложение. Я немного погуглил ( Разгрузка классов в Java?, Динамически загружаемые и выгружаемые модули приложения в Java - как?) И нашел 3 возможных решения:
- OSGI, который выглядит слишком сложным для моих целей: разгрузка классов - единственное, что мне нужно из этой мощной спецификации.
- Собственная реализация, которая подразумевает создание собственного Classloader, загрузку jar-файлов с его помощью и, когда придет время, чтобы закрыть jar - открыть экземпляр Classloader для GC и надеяться, что GC удалит его вместе со всеми загруженными jar-файлами, что может произойти не сразу.
- Скопируйте материал, который делают серверы приложений:). Это цель моего вопроса.
Есть ли объяснение того, как Tomcat выгружает классы (войны)? Можно ли повторно использовать это в моем приложении?
PS Как раз в то время, когда я писал этот пост, мне в голову пришли 2 странные идеи:
- может быть, мы сможем запустить другой экземпляр приложения с новым набором jar-файлов и переключить потоки входных и выходных данных со старого на новый. Если есть место для сохранения состояния - это может быть быстрее, чем полный перезапуск.
- может быть весна может помочь? Он может динамически регистрировать бины, но это выглядит как некрасивое решение, и он все равно не может их выгружать; может быть, Spring Boot может помочь?
3 ответа
Класс может быть выгружен только тогда, когда он и его загрузчик классов недоступны и, следовательно, пригодны для сборки мусора. Поскольку загрузчик классов может достигать каждого загруженного им класса, и каждый класс, загруженный загрузчиком классов, может достигать своего загрузчика классов, и каждый объект, который является экземпляром класса, может достигать его класса, это означает, что загрузчик классов, все загруженные им классы и все объекты, которые являются экземплярами этих классов, должны быть недоступны и иметь право на сборку мусора. Только тогда класс может быть "выгружен", когда этот полный граф объектов будет собран мусором.
Я могу лишь частично ответить на ваши вопросы, но лучше, чем ничего... Вы правы, модульность - довольно утомительная тема (по крайней мере, до появления Java 9).
Идея объявления 2 (Spring): Я уже потратил некоторые мысли на Spring Boot здесь и пришел к выводу, что я буду придерживаться либо OSGI (оно того стоит), либо чисто микросервисной архитектуры.
Я полагаю, что вы не выполняете полное перераспределение приложения, но не хотите перезапускать все приложение каждый раз, когда вы его разрабатываете
Если вы хотите изменить функциональность методов без изменения класса или сигнатур методов, вы можете использовать Spring Loaded.
Добавьте зависимость к вашему проекту https://mvnrepository.com/artifact/org.springframework/springloaded/1.2.6.RELEASE
Установить параметр JVM -javaagent: путь \springloaded-version.jar -noverify
Эта опция может быть установлена несколькими способами в зависимости от того, как вы запускаете tomcat
У меня есть веб-сайт Broadleaf eccomerce, и я добавил эту опцию в MAVEN_OPTS в пакетном скрипте, который запускает встроенный tomcat, или вы можете настроить его в разделе Запуск конфигурации для опций Tomcat VM
прочитайте http://docs.spring.io/spring-boot/docs/current/reference/html/howto-hotswapping.html