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

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

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

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

9 ответов


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

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

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

есть несколько способов реализовать это. Для пример:

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

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

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

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

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

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

" самый лучший " путь зависит от ваших специфических требований.

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

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

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


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


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

упакуйте приложение updater в самом обновлении.

приложение: когда приложение обнаруживает более новую версию, оно делает следующее:

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

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

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

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


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

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


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

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

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

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


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

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

Он будет легко начать новую версию без перезагрузки.


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

вы можете написать загрузочное приложение (ala World of Warcraft launcher, Если Вы играли в WoW). Этот bootstrap отвечает за проверку обновлений.

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

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

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

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

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


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


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

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

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

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

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