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

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

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

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

Ответ 1

Основная структура решения такова:

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

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

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

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

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

Преимущества внешнего метода обертки:

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

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

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

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

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

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

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


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

Ответ 2

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

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

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

  • Загрузить обновление (Zipfile)
  • Извлечь приложение и ApplicationUpdater (все в zip файле)
  • Запустить программу обновления

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

  • Остановить приложение (в моем случае - демон через init.d)
  • Скопируйте загруженный файл jar, чтобы перезаписать текущее приложение
  • Запустите приложение
  • Cleanup.

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

Ответ 3

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

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

Ответ 4

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

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

  • Приложение должно быть самовосстанавливающимся и продолжать работать даже во время обновления (серверное приложение, встроенные приложения). Перейдите в OSGi: Bundles или Equinox p2.

  • Приложение представляет собой настольное приложение и имеет установщик. Существует множество инсталляторов с опцией обновления. Проверьте список установщиков.

Ответ 5

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

Ответ 6

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

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

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

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

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

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

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

Ответ 7

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

Ответ 8

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

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

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

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

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