Обновление JAR во время работы
Учитывая, что jar работает в JVM, можно будет выгрузить текущий Jar и удалить его из системы. Загрузите новую версию и переименуйте ее с тем же именем последнего Jar, а затем инициализируйте новый Jar, создав плавное обновление Jar в JVM. Возможно ли даже поручить JVM выполнить это действие? Возможно ли даже обновить Jar во время его запуска?
Ответы
Ответ 1
Загрузите новую версию и переименуйте ее с тем же именем последнего Jar и затем инициализируйте новый Jar, создавая бесшовное обновление Jar внутри JVM... Возможно ли даже обновить банку во время ее запуска?
JAR файл не работает, JVM запущен. Ваш JAR файл просто содержит информацию о классе (так называемые байтовые коды), которые делают JVM полезной. В большинстве случаев JVM фактически не будет блокировать системную блокировку вашего JAR файла, поэтому вы можете заменить этот файл на свой контент.
Реальная проблема, конечно, в том, что, как только JVM загрузит ваш JAR, он будет успешно перемещаться с тем, что он загрузил и никогда не читает из вашего JAR файла, независимо от того, сколько раз вы его перезаписываете. Это поведение загрузчика классов по умолчанию и не может быть изменено - однако, как указывали другие, вы не должны использовать загрузчик классов по умолчанию. Вы можете реализовать свои собственные, аналогичные тем, что используют серверы веб-приложений, для загрузки обновленных JARS из файловой системы. Предостережение - определение собственного загрузчика классов считается "плохим идеей", если вы действительно не знаете, что делаете. Вы можете прочитать здесь здесь и здесь.
Ответ 2
Это то, что я видел много раз раньше (а также сделал сам). Я составил несколько точек проблем/решений, которые могут возникнуть.
- JVM сработает с дампом, если вы перезапишете файл JAR, который он будет использовать позже.
- Позже я подразумеваю, что классы загружаются довольно лениво, а некоторые могут быть загружены позже в вашей жизни программы.
- JVM имеет открытый дескриптор для JAR файла, и lib будет терпеть неудачу, поскольку JAR и указатели станут неправильными
- Вероятность может быть уменьшена путем предварительной загрузки всех классов и ресурсов из файла JAR
- Если у вас есть пользовательский загрузчик классов, вы можете сами закрыть дескрипторы.
- Вам нужно знать, как выполняется загрузка классов. Еще лучше контролировать.
- Пользовательский загрузчик классов, который будет создавать загрузчики классов для JAR и управлять версиями
- Знайте, как ваше приложение использует загрузчики классов и как оно действует на новых JAR (например, проверьте, что делает Tomcat при перезаписывании архива WAR)
- В Windows ваши файлы JAR будут заблокированы, и вы не сможете их перезаписать. Если вы находитесь под контролем, вы можете разблокировать их после использования (закрыть их). Для сторонних систем вы должны найти соответствующие флаги. Например, вы можете проверить конфигурацию antiJARLocking в Tomcat.
- Всегда лучше избегать перезаписывания одного и того же файла и, скорее, иметь некоторое управление версиями
В общем, есть много проблем, с которыми вы могли столкнуться, когда хотите выполнить перезагрузку JAR. К счастью, существуют способы минимизации рисков. Самый безопасный способ - сделать что-то подобное, чтобы получить тот же эффект. Cleanest - это пользовательские загрузчики классов и управление версиями JAR файлов.
Ответ 3
Как правило, вы не можете этого сделать, поскольку это поведение, насколько мне известно, официально не определено.
Однако вы можете создать загрузчик классов, используя файл jar за пределами вашего официального пути к классам, а затем загружать классы из них по мере необходимости. Отбрасывая все экземпляры классов, загружаемых загрузчиком классов, вы можете удалить текущие ресурсы, а затем создать новый загрузчик классов в новом файле jar, а затем загрузить новые классы и создать новые объекты.
Это довольно сложно, поэтому, возможно, вы вместо этого сделаете банку модуль OSGi и вызовите свою программу через OSGi-загрузчик?
Ответ 4
Вы не можете писать в банку, которая работает. Для записи не существует эквивалента getResourceInputStream. Я думаю, что если вы попытаетесь написать с помощью FileOutputStream, поскольку JVM использует его, вы не сможете его удалить, поскольку система его предотвратит.
Во всяком случае, все еще можно предлагать обновления разных модулей в разных банках. Таким образом, вы можете представить себе файл основного jar приложения, который может быть обновлен через небольшой независимый исполняемый файл jar, содержащий обновление.
Также возможно использовать JNLP для автоматического и бесшовного обновления приложения.
Приложения на стороне сервера также являются альтернативой скрыть обновления для пользователя.
С уважением,
Stéphane
Ответ 5
Ответ лежит на загрузчиках классов Java. Эти парни загружают классы из JARS или .class файлов или значение byte[]
или URL-адрес или что-то еще. Всякий раз, когда вы получаете доступ к классу, вы неявно используете загрузчик классов, чтобы дать вам правильный экземпляр класса.
Создайте загрузчик классов по вашему выбору и просто переключите загрузчик классов, когда вам нужно "обновить" ваши классы. Взгляните на метод Thread.setContextClassLoader - это изменит загрузчик классов Thread.
Определение собственного загрузчика классов очень просто - просто подклассифицируйте класс ClassLoader
и переопределите его метод findClass.