我怎样才能编写一个可以在运行时自行更新的Java应用程序?

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

什么是最好的方式来做到这一点,这是可能的?

我猜应用程序可以下载一个新的.jar文件并启动它。 但是,我应该怎么做切换,例如知道什么时候新的应用程序启动,然后退出。 还是有更好的方法来做到这一点?

解决scheme的基本结构如下:

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

  • 该应用程序做它的事情,但定期检查下载URL。 如果它检测到新版本,则退出到启动器。

有很多方法可以实现这一点。 例如:

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

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

外部包装方法的优点是:

  • 你只需要一个JAR,
  • 你可以replace整个Java应用程序,
  • 由应用程序创build的任何辅助线程等都将消失,而没有特殊的closures逻辑
  • 你也可以处理从应用程序崩溃等恢复。

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

  • 该解决scheme是纯Java和便携式的,
  • 转换会更快,而且
  • 你可以在重启时更容易保留状态(模泄漏问题)。

“最好”的方式取决于你的具体要求。

还应该指出的是:

  • 自动更新存在安全风险。 一般而言,如果提供更新的服务器遭到破坏,或者提供更新的机制容易受到攻击,则自动更新可能会导致客户端的妥协。

  • 向客户推送更新会对客户造成损害,这可能会带来法律风险,并对您的业务声誉构成风险。


如果你能find一种方法来避免重新发明轮子,那就太好了。 请参阅其他答案的build议。

我目前正在开发一个JAVA Linux守护进程,同时也需要实现一个自动更新机制。 我想限制我的应用程序到一个jar文件,并提出了一个简单的解决scheme:

在更新本身中包装更新程序应用程序。

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

  1. 下载更新(Zipfile)
  2. 提取应用程序和ApplicationUpdater (全部在zip文件中)
  3. 运行更新程序

ApplicationUpdater :更新程序在运行时执行以下操作:

  1. 停止应用程序(在我的情况下通过init.d守护进程)
  2. 复制下载的jar文件覆盖当前的应用程序
  3. 启动应用程序
  4. 清理。

希望它可以帮助别人。

我编写了一个Java应用程序,可以在运行时加载插件,并立即开始使用它们,这受到了jEdit中类似机制的启发。 jEdit是开源的,所以你可以select看看它是如何工作的。

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

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

你需要考虑两种情况:

  1. 应用程序需要自我更新,即使在更新期间也能保持运行(服务器应用程序,embedded式应用程序)。 使用OSGi: Bundles或Equinox p2 。

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

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

这不一定是最好的方法,但它可能适合你。

你可以写一个bootstrap应用程序(如果你玩过魔兽世界,那么魔兽世界的启动器就是ala)。 该引导程序负责检查更新。

  • 如果有更新可用,它将提供给用户,处理下载,安装等。
  • 如果应用程序是最新的,它将允许用户启动应用程序
  • 或者,您可以允许用户启动应用程序,即使它不是最新的

这样,您不必担心强制退出应用程序。

如果您的应用程序是基于Web的,并且它们有一个最新的客户端很重要,那么您也可以在应用程序运行时进行版本检查。 您可以在执行与服务器的正常通信(部分或全部呼叫)或两者的同时,间隔地执行这些操作。

对于我最近处理的产品,我们在启动时进行了版本检查(没有引导程序的应用程序,但在出现主窗口之前),以及在调用服务器期间。 当客户端过期时,我们依靠用户手动退出,但禁止对服务器进行任何操作。

请注意,在调出主窗口之前,我不知道Java是否可以调用UI代码。 我们正在使用C#/ WPF。

如果您使用Equinox插件构build应用程序,则可以使用P2 Provisioning System获得现成的解决scheme来解决此问题。 这将需要服务器在更新后自行重启。

当下载一个新的jar(例如,一个中间人攻击的人)时,我看到一个安全问题。 你总是必须签署你的下载更新。

在JAX2015上,Adam Bien讲述了如何使用JGit来更新二进制文件。 可悲的是我找不到任何教程。

来源德文。

亚当·比恩创造更新在这里看到

我用一些javaFX前端在这里分叉它。 我也在进行自动签名。

Interesting Posts