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