如何编写可在运行时自行更新的Java应用程序?

Jon*_*nas 82 java jar auto-update server-application

我想实现一个java应用程序(服务器应用程序),它可以从给定的URL下载新版本(.jar文件),然后在运行时更新自己.

这样做的最佳方式是什么?是否可能?

我猜应用程序可以下载一个新的.jar文件并启动它.但是我应该如何进行切换,例如知道新应用程序何时启动然后退出.或者有更好的方法吗?

Ste*_*n C 60

解决方案的基本结构如下:

  • 有一个主循环负责重复加载最新版本的应用程序(如果需要)并启动它.

  • 应用程序执行其操作,但会定期检查下载URL.如果它检测到新版本,它会退回到启动器.

您可以通过多种方式实现此目的.例如:

  • 启动程序可以是包装脚本或二进制应用程序,它启动新的JVM以从被替换的JAR文件运行应用程序.

  • 启动程序可以是一个Java应用程序,它为新JAR创建一个类加载器,加载一个入口点类并在其上调用一些方法.如果你这样做,你必须注意类加载器存储泄漏,但这并不困难.(您只需要确保在重新启动后没有可以从JAR加载类的对象.)

外部包装方法的优点是:

  • 你只需要一个JAR,
  • 你可以替换整个Java应用程序,
  • 应用程序等创建的任何辅助线程都将在没有特殊关闭逻辑的情况下消失
  • 您还可以处理应用程序崩溃等的恢复.

第二种方法需要两个JAR,但具有以下优点:

  • 解决方案是纯Java和便携式,
  • 转换会更快,而且
  • 您可以更轻松地在重新启动时保持状态(模数泄漏问题).

"最佳"方式取决于您的具体要求.

还应该指出:

  • 自动更新存在安全风险.通常,如果提供更新的服务器受到威胁,或者提供更新的机制易受攻击,则自动更新可能导致客户端的危害.

  • 向客户推送可能对客户造成损害的更新可能会产生法律风险,并可能对您的企业声誉造成风险.


如果你能找到一种避免重新发明轮子的方法,那就太好了.请参阅其他答案以获取建议.


小智 39

我目前正在开发JAVA Linux守护进程,并且还需要实现自动更新机制.我想将我的应用程序限制为一个jar文件,并提出了一个简单的解决方案:

将更新程序应用程序打包在更新本身中.

应用程序:当应用程序检测到较新版本时,它会执行以下操作:

  1. 下载更新(Zipfile)
  2. 提取Application 和ApplicationUpdater(全部在zipfile中)
  3. 运行更新程序

ApplicationUpdater:当updater运行时,它执行以下操作:

  1. 停止应用程序(在我的例子中是一个通过init.d的守护进程)
  2. 复制下载的jar文件以覆盖当前的应用程序
  3. 启动应用程序
  4. 清理.

希望它可以帮助某人.


Bra*_*ace 10

我编写了一个Java应用程序,它可以在运行时加载插件并立即开始使用它们,受到jEdit中类似机制的启发.jEdit是开源的,因此您可以选择查看其工作原理.

该解决方案使用自定义ClassLoader从jar加载文件.一旦它们被加载,你可以从新的jar中调用一些方法作为它的main方法.然后棘手的部分是确保你摆脱旧代码的所有引用,以便它可以被垃圾收集.我不是那方面的专家,我已经成功了,但这并不容易.


Pet*_*ego 9

这是一个已知的问题,我建议不要重新发明轮子 - 不要写自己的黑客,只使用其他人已经做过的事情.

您需要考虑两种情况:

  1. 应用程序需要可自行更新,并且即使在更新期间也能继续运行(服务器应用程序,嵌入式应用程序)使用OSGi:BundlesEquinox p2.

  2. App是一个桌面应用程序,并有一个安装程序.有许多安装程序具有更新选项.检查安装程序列表.


jnr*_*jnr 5

  1. 第一种方式:使用tomcat和它的部署工具.
  2. 第二种方式:将应用程序分为两部分(功能和更新),让更新部分替换功能部分.
  3. 第三种方式:在你的服务器应用程序中只下载新版本,然后旧版本发布绑定端口,然后旧版本运行新版本(启动进程),然后旧版本在应用程序端口上发送请求到新版本删除旧版本,旧版本终止,新版本删除旧版本.像这样: 替代文字


Mor*_*hai 5

我最近创建了与Java 9的模块系统完全兼容的update4j

它将无缝启动新版本,而无需重新启动。