Как я могу написать приложение Java, которое может обновляться во время выполнения? - PullRequest
81 голосов
/ 23 октября 2010

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

Каков наилучший способ сделать это и возможно ли это?

Я полагаю, что приложение может загрузить новый файл .jar и запустить его. Но как я должен сделать передачу, например знать, когда новое приложение запускается, а затем выйти. Или есть лучший способ сделать это?

Ответы [ 9 ]

58 голосов
/ 23 октября 2010

Базовая структура решения выглядит следующим образом:

  • Существует основной цикл, отвечающий за повторную загрузку последней версии приложения (при необходимости) и ее запуск.

  • Приложение делает свое дело, но периодически проверяет URL-адрес загрузки.Если он обнаруживает новую версию, он возвращается обратно в панель запуска.

Существует несколько способов реализовать это.Например:

  • Средство запуска может быть сценарием-оберткой или двоичным приложением, которое запускает новую JVM для запуска приложения из заменяемого файла JAR.

  • Средство запуска может быть приложением Java, которое создает загрузчик классов для нового JAR, загружает класс точки входа и вызывает для него некоторый метод.Если вы делаете это таким образом, вы должны следить за утечками памяти загрузчика классов, но это не сложно.(Вам просто нужно убедиться, что ни один объект с классами, загруженными из JAR, не будет доступен после перезапуска.)

Преимущества подхода с использованием внешней оболочки:

  • вам нужен только один JAR,
  • , вы можете заменить все Java-приложение,
  • любые вторичные потоки, созданные приложением и т. Д., Исчезнут без специальной логики выключения и
  • вы также можете иметь дело с восстановлением после сбоев приложений и т. Д.

Второй подход требует двух JAR, но имеет следующие преимущества:

  • решение чистоJava и портативные,
  • переключение будет быстрее, и
  • вы сможете легче сохранять состояние при перезапуске (проблемы утечки по модулю).

Лучшее«Способ зависит от ваших конкретных требований.

Следует также отметить, что:

  • При автоматическом обновлении существуют угрозы безопасности.В целом, если сервер, предоставляющий обновления, скомпрометирован или если механизмы предоставления обновлений подвержены атакам, автоматическое обновление может привести к компрометации клиента (ов).

  • Отправка обновления клиенту, которое может нанести ущерб клиенту, может иметь юридические риски и риски для репутации вашего бизнеса.


Если вы можете найти способчтобы не изобретать велосипед, это было бы хорошо.Смотрите другие ответы для предложений.

36 голосов
/ 12 ноября 2012

В настоящее время я занимаюсь разработкой JAVA Linux Daemon, а также мне нужно было внедрить механизм автообновления.Я хотел ограничить свое приложение одним файлом jar и предложил простое решение:

Упаковать приложение обновления в само обновление.

Приложение: Когда приложение обнаруживает более новую версию, оно выполняет следующие действия:

  1. Загрузка обновления (Zipfile)
  2. Извлечение приложения и ApplicationUpdater (все вzipfile)
  3. Запустить программу обновления

ApplicationUpdater : при запуске программы обновления выполняется следующее:

  1. Остановить приложение (вв моем случае демон через init.d)
  2. Скопируйте загруженный файл JAR для перезаписи текущего приложения
  3. Запустите приложение
  4. Очистка.

Надеюсь, это кому-нибудь поможет.

10 голосов
/ 23 октября 2010

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

В решении используется пользовательский ClassLoader для загрузки файлов из фляги.После загрузки вы можете вызвать какой-либо метод из нового jar, который будет действовать как его main метод.Тогда сложная часть заключается в том, чтобы избавиться от всех ссылок на старый код, чтобы его можно было собирать мусором.Я не совсем эксперт в этой части, я заставил это работать, но это было нелегко.

9 голосов
/ 26 октября 2010

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

Две ситуации, которые вам нужно рассмотреть:

  1. Приложение должно быть самообновляемым и продолжать работу даже во время обновления (серверное приложение, встроенные приложения).Выберите OSGi: Связки или Equinox p2 .

  2. Приложение представляет собой приложение для настольного компьютера и имеет установщик.Есть много инсталляторов с возможностью обновления.Проверьте список установщиков .

5 голосов
/ 12 марта 2018

Я недавно создал update4j , который полностью совместим с модульной системой Java 9.

Он без проблем запустит новую версию без перезапуска.

5 голосов
/ 23 октября 2010
  1. Первый способ: использовать tomcat и средства его развертывания.
  2. Второй способ: разделить приложение на две части (функциональная и обновленная) и позволить обновленной части заменить функциональную часть.
  3. Третий способ: в вашем серверном приложении просто загрузите новую версию, затем старая версия освобождает связанный порт, затем старая версия запускает новую версию (запускает процесс), затем старая версия отправляет запрос на порт приложения новой версии, чтобы удалить старую версию, старую версиюзавершается и новая версия удаляет старую версию.Как это: alt text
2 голосов
/ 23 октября 2010

Это не обязательно лучший способ, но он может сработать для вас.

Вы можете написать приложение для начальной загрузки (так называемое средство запуска World of Warcraft, если вы игралиВот это да).Этот загрузчик отвечает за проверку обновлений.

  • Если доступно обновление, оно предложит его пользователю, выполнит загрузку, установку и т. Д.
  • Если приложениена текущий момент, это позволит пользователю запускать приложение
  • При желании вы можете разрешить пользователю запускать приложение, даже если оно не устарело

Этото есть вам не нужно беспокоиться о принудительном выходе из вашего приложения.

Если ваше приложение работает в Интернете и важно, чтобы у него был обновленный клиент, вы также можете выполнить проверку версий.пока приложение работает.Вы можете делать их через определенные промежутки времени, выполняя обычную связь с сервером (некоторые или все вызовы), или и то, и другое.

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

Обратите внимание, что я не знаю, может ли Java вызывать код пользовательского интерфейса до того, как вы откроете свойглавное окноМы использовали C # / WPF.

1 голос
/ 26 октября 2010

Если вы создаете свое приложение с помощью плагинов Equinox , вы можете использовать P2 Provisioning System , чтобы получить готовое решение этой проблемы. Это потребует перезагрузки сервера после обновления.

0 голосов
/ 17 сентября 2015

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

На JAX2015 Адам Бьен рассказал об использовании JGit для обновления двоичных файлов. К сожалению, я не смог найти учебники.

Источник на немецком языке.

Адам Бьен создал программу обновления см. Здесь

Я его разветвил здесь с некоторым интерфейсом javaFX. Я также работаю над автоматической подписью.

...