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