Горячая замена файлов jar в java

У меня есть два jar-файла. Один.jar содержит основной метод для запуска процесса, а два других.jar содержат только файлы классов.

В One.jar я упомянул two.jar в своем пути к классам манифеста.

One.jar содержит механизм динамической загрузки классов с помощью Class.forName().

Я хочу развернуть One.jar только один раз на всю жизнь. Никаких изменений в него вносить не будет.

Изменения будут происходить только в two.jar

Я хочу заменить файл two.jar на обновленный файл two.jar. Я видел и другие сообщения о горячей замене, такие как OSGi, горячая замена для ANT, но мне ничего не помогает.

После небольшого исследования выяснилось, что JRebel делает это действительно лучше, но я действительно не знаю, как интегрировать его с этими банками? Я застрял на этом в течение почти 2 дней. Просто нужно несколько шагов информации, чтобы сделать это. Кто-нибудь, помогите мне, пожалуйста... Это действительно очень важно для меня... Спасибо.


person Sri777    schedule 03.01.2014    source источник
comment
просто поместите банку в ожидаемый каталог. если вы действительно просто загружаете классы, если jar находится в вашем пути к классам, он найдет классы. Здесь не нужно ничего особенного, если только ваша программа не работает 24/7, потому что тогда она не освободит классы из банки.   -  person SnakeDoc    schedule 04.01.2014
comment
Чтобы заменить определение класса, вам нужно иметь собственный загрузчик классов для чтения two.jar. Затем вы отбрасываете этот загрузчик классов, чтобы избавиться от старого jar-файла в памяти (а также всех его объектов) и создаете новый для чтения нового jar-файла.   -  person Thorbjørn Ravn Andersen    schedule 04.01.2014
comment
@SnakeDoc Я не пробовал это в Java 7, но в Java 6 ниже JVM блокирует файлы, что затрудняет их замену ... кроме того, как JVM узнает, что Jars были заменены?   -  person MadProgrammer    schedule 04.01.2014
comment
редактировать: упс, мысли @MadProgrammer были OP! вы пишете программу, которая работает 24/7? Если JVM завершает работу (конец программы), то jar-файлы/классы всегда следует освобождать. Если ваша программа работает круглосуточно и без выходных (например, сервер приложений и т. д.), вам понадобится что-то более мощное, например OSGi или JBoss/Glassfish и т. д. Но это большие тяжелые контейнеры Java EE, и если ваша программа не такого типа, нет смысла добавлять все эти накладные расходы для этого.   -  person SnakeDoc    schedule 04.01.2014
comment
@SnakeDoc У меня просто была возможность горячей замены, что исключало бы простое попадание в банки ... Потратил много времени на написание процесса обновления, который мог бы преодолеть это для нашего (очень плохо) написанного приложения - я просто говорю ;). Наше решение: стоп, копирование, запуск, которое, я полагаю, похоже на то, что вы предлагаете.   -  person MadProgrammer    schedule 04.01.2014
comment
@RomanVottner Да, я бы подумал об этом. Единственная проблема заключается в том, чтобы знать, когда что-то меняется, и иметь возможность удалить текущий загрузчик классов и загрузить новый... но это все просто контекст... ;)   -  person MadProgrammer    schedule 04.01.2014
comment
@MadProgrammer верно, это то, что я предлагал, если приложению не нужно работать 24/7 (например, период обслуживания и т. д.). Явно низкотехнологичное решение. Другим способом было бы реализовать промежуточный каталог, поместить в него новую банку и заставить службу наблюдателя за папками время от времени сканировать этот каталог, если найдена банка, выгрузить предыдущую, удалить ее, скопировать банку промежуточной области. загрузите его через загрузчик классов. Таким образом, вы также можете немного изолировать внутренности вашей программы от пользователей.   -  person SnakeDoc    schedule 04.01.2014
comment
@SnakeDoc Я могу с уверенностью сказать, что это своего рода ошибка в Java 7. Я пытаюсь сделать это на платформе Windows и думаю, что это блокирует файл jar. Даже странная вещь, которую я видел, заключается в том, что я не могу удалить two.jar во время работы JVM, поскольку она заблокирована, но я могу заменить ее обновленным two.jar, и изменения не отображаются.   -  person Sri777    schedule 05.01.2014
comment
@RomanVottner Как вы думаете, если я заменю файл jar на платформе Linux, изменения вступят в силу?   -  person Sri777    schedule 05.01.2014
comment
@ ThorbjørnRavnAndersen Спасибо за ваше предложение. Можете ли вы помочь мне с небольшим кодом, пожалуйста? Я пробовал System.gc() и даже отключал переменную memorymap... у меня ничего не работает.   -  person Sri777    schedule 05.01.2014
comment
@MadProgrammer и все остальные ребята, я действительно хочу поблагодарить вас за ваши ценные ответы на мой вопрос. Поскольку это мой первый вопрос в переполнении стека, и я думал, что ответов будет минимум, но это здорово. Еще раз спасибо, что помогли мне :)   -  person Sri777    schedule 05.01.2014


Ответы (2)


Привет всем, у меня наконец-то есть решение для этого. Я действительно не знаю, что я придумаю такое простое решение. Я взял идею @Thorbjørn Ravn Andersen. Все, что я сделал, это сначала получил временную метку файла jar, а затем загрузил jar с помощью URLClassLoader. Если временная метка файла jar изменяется (т. е. когда я заменяю jar обновленным jar), то я отбрасываю старый объект URLClassLoader, используя close(), и снова загружаю новый jar с помощью URLClassLoader. Единственное, что мне нужно каждый раз проверять, это меняется ли временная метка jar или нет. Надеюсь, этот ответ поможет и другим людям. Спасибо всем за вашу поддержку.

person Sri777    schedule 08.01.2014

Поскольку я имею непосредственное отношение к JRebel (я менеджер по продукту), я, вероятно, могу дать несколько советов по настройке.

Чтобы обновить классы в JAR-файле с помощью JRebel, поместите в этот файл two.jar специальный файл конфигурации rein.xml, который будет указывать на каталог, в котором находятся скомпилированные классы two.jar.

     one.jar ---> two.jar
                   `- rebel.xml   // points to two/project/classes

Вот документ с примерами: http://manuals.zeroturnaround.com/jrebel/standalone/config.html#configuring-jars

В зависимости от того, как настроен ваш проект, плагины IDE помогут автоматизировать это.

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

person Anton Arhipov    schedule 05.01.2014
comment
Спасибо Антон за ответ. Да, мой проект будет запущен через несколько дней, и поэтому мы думаем о горячих развертываниях, чтобы сэкономить время. Если вы считаете, что JRebel мне не подходит, не могли бы вы предложить мне какой-нибудь другой инструмент? - person Sri777; 05.01.2014
comment
JRebel не устраняет технические ограничения платформы JVM в отношении горячего развертывания на действующих системах. Он разработан исключительно как инструмент разработки, и лицензионное соглашение с конечным пользователем ограничивает его использование в производстве. Существует еще один инструмент от того же поставщика — LiveRebel (zeroturnaround.com/software/liverebel), который предназначен для автоматизации развертывания приложений, так что вы можете взглянуть. Если интересно, попросите демо через веб-сайт. - person Anton Arhipov; 05.01.2014
comment
@AntonArhipov, просто чтобы прояснить ситуацию - не могли бы вы указать свою принадлежность к JRebel в своем ответе? - person Thorbjørn Ravn Andersen; 05.01.2014
comment
@ ThorbjørnRavnAndersen готово (хотя это все равно есть в моем профиле) - person Anton Arhipov; 05.01.2014