我想实现一个 java 应用程序(服务器应用程序),它可以从给定的 url 下载新版本(.jar 文件),然后在运行时自行更新。
最好的方法是什么,这可能吗?
我猜该应用程序可以下载一个新的 .jar 文件并启动它。但是我应该如何进行切换,例如知道新应用程序何时启动然后退出。还是有更好的方法来做到这一点?
我想实现一个 java 应用程序(服务器应用程序),它可以从给定的 url 下载新版本(.jar 文件),然后在运行时自行更新。
最好的方法是什么,这可能吗?
我猜该应用程序可以下载一个新的 .jar 文件并启动它。但是我应该如何进行切换,例如知道新应用程序何时启动然后退出。还是有更好的方法来做到这一点?
解决方案的基本结构如下:
有一个主循环负责重复加载应用程序的最新版本(如果需要)并启动它。
应用程序会做它的事情,但会定期检查下载 URL。如果它检测到新版本,它会退出到启动器。
有多种方法可以实现这一点。例如:
启动器可以是一个包装脚本或二进制应用程序,它启动一个新的 JVM 以从被替换的 JAR 文件运行应用程序。
启动器可以是一个 Java 应用程序,它为新 JAR 创建一个类加载器,加载一个入口点类并在其上调用一些方法。如果你这样做,你必须注意类加载器存储泄漏,但这并不难。(您只需要确保在重新启动后无法访问具有从 JAR 加载的类的对象。)
外部包装方法的优点是:
第二种方法需要两个 JAR,但具有以下优点:
“最佳”方式取决于您的具体要求。
还应该注意的是:
自动更新存在安全风险。一般来说,如果提供更新的服务器受到攻击,或者提供更新的机制容易受到攻击,那么自动更新可能会导致客户端受到攻击。
向客户推送对客户造成损害的更新可能会带来法律风险,并对您的企业声誉造成风险。
如果你能找到一种方法来避免重新发明轮子,那就太好了。有关建议,请参阅其他答案。
我目前正在开发一个 JAVA Linux 守护进程,并且还需要实现自动更新机制。我想将我的应用程序限制为一个 jar 文件,并提出了一个简单的解决方案:
将更新程序应用程序打包到更新本身中。
应用程序:当应用程序检测到较新版本时,它会执行以下操作:
ApplicationUpdater:当更新程序运行时,它会执行以下操作:
希望它可以帮助某人。
我最近创建了update4j,它与 Java 9 的模块系统完全兼容。
它将无缝启动新版本而无需重新启动。
这是一个已知问题,我建议不要重新发明轮子——不要编写自己的 hack,只需使用其他人已经做过的。
您需要考虑两种情况:
应用程序需要是可自我更新的,并且即使在更新期间也能保持运行(服务器应用程序、嵌入式应用程序)。使用 OSGi:Bundles或Equinox p2。
应用程序是一个桌面应用程序,并有一个安装程序。有许多带有更新选项的安装程序。检查安装程序列表。
受 jEdit 中类似机制的启发,我编写了一个 Java 应用程序,它可以在运行时加载插件并立即开始使用它们。jEdit 是开源的,因此您可以选择查看它是如何工作的。
该解决方案使用自定义 ClassLoader 从 jar 加载文件。一旦它们被加载,你就可以从新的 jar 中调用一些方法来作为它的main
方法。然后棘手的部分是确保您摆脱对旧代码的所有引用,以便它可以被垃圾收集。我不是这方面的专家,我已经做到了,但这并不容易。
这不一定是最好的方法,但它可能对你有用。
您可以编写一个引导应用程序(如果您玩过《魔兽世界》,那是魔兽世界的启动器)。该引导程序负责检查更新。
这样您就不必担心强制退出您的应用程序。
如果您的应用程序是基于 Web 的,并且如果他们拥有最新的客户端很重要,那么您还可以在应用程序运行时进行版本检查。您可以在与服务器(部分或全部调用)进行正常通信时,或两者同时执行这些操作。
对于我最近开发的产品,我们在启动时(没有引导程序应用程序,但在主窗口出现之前)以及调用服务器期间进行了版本检查。当客户端过期时,我们依靠用户手动退出,但禁止对服务器进行任何操作。
请注意,在您打开主窗口之前,我不知道 Java 是否可以调用 UI 代码。我们使用的是 C#/WPF。
如果您使用Equinox插件构建应用程序,则可以使用P2 Provisioning System来获得针对此问题的现成解决方案。这将要求服务器在更新后自行重启。