繁体   English   中英

Java-如何替换正在运行的jar文件

[英]Java - How to replace a running jar file

我希望我的Java应用程序能够自动保持最新,我已经制作了所有代码来下载最新的jar文件并将其放在指定的路径中,但是由于我的程序必须打开才能实际检查是否有更新可用,然后更新它们,这给了我这个错误:

Exception in thread "main" java.nio.file.FileSystemException: name.jar: The process cannot access the file because it is being used by another process

现在我的问题不是为什么会出现此错误,因为很明显为什么,问题是:由于必须打开才能实际下载更新,因此我将如何成功地成功更新.jar文件? 如果有其他选择,我宁愿不要使另一个.jar充当独立的更新程序。

我用来测试的代码示例:

    URL url = new URL("<working url to the .jar file>");
    InputStream in = url.openStream();
    Files.copy(in, Paths.get("app.jar"), StandardCopyOption.REPLACE_EXISTING);
    in.close();

首先:另一个答案是正确的,有一些方法可以静默更新/重新启动JAR文件。 并重新启动下载新的JAR,就可以了。

但是问题是关于更新“使用中的” JAR的,为此,我有一个明显的答案:您的想法是错误的!

即使以某种方式破解您的方式进入重载JAR文件的文件系统上,而一个(或多个)有(或没有)的JVM装入从JAR运行类,结果不是你指望它有什么是:替换JAR文件内容不会神奇地将所有类重新加载到正在运行的JVM中。 该类已加载! 在文件系统中更改其“加载源” 不会影响“正在运行”的类。

如果有,请启用以下情况:

  • 从Jar X(版本N)加载A类
  • Jar X已更新
  • 从Jar X(版本N + m)加载B类

但是,请注意,B类希望A类的外观有所不同 突然之间,您在该JVM实例中存在版本冲突。 因为它从X(版本N)加载了某些类,并且从X(版本N + 1或N + 5)加载了其他类,因为该客户跳过了2周的下载。 而且情况变得更糟:确切的错误情况可能完全取决于JVM到目前为止所看到的工作负载以及更新后的使用方式。 一个客户可能没有任何问题,而另一个可能在5分钟内崩溃(尽管很可能在某个时候崩溃)。

长话短说:不要这样做。 代替:

  • 要么告诉您的用户,当有更新进来时,他们必须重新启动应用程序
  • 或研究“真正的” JVM热交换机制。 但老实说:这更多是一种调试功能,您可以在开发环境中(例如,使用JRebel之类的工具)来实现。 不想在你的客户使用它在生产环境中。 因为如上所述,运行时版本控制问题很严重

首先,要在不重启应用程序的情况下替换正在运行的应用程序几乎是不可能的,但是有些技术可以流畅地进行转换。 这是一个流行的(简单的):

  • 您启动application.exe ,它检查版本并发现有新版本。
  • application.exe启动updater.exe并自行关闭(或等待,直到下载了更新版本,然后自行关闭。
  • updater.exe替换该文件,然后再次启动application.exe

因此,据我所知,这部分是主要内容(取代了核心应用程序),没有任何硬编码内存黑客。

如果您不需要更新实际的核心应用程序,并且愿意花时间在应用程序中开发动态库/资产管理,则可以从本质上卸载库或资产,从application.exe更新它,然后重新加载它。完成更新后,无需重新启动应用程序。

这可能就是您要寻找的东西,因为如果您的application.exe只是一个加载程序,并且应用程序的核心逻辑是库之一,则您可以实质上替换应用程序的任何部分。 您仍然必须“重新启动”应用程序的该部分,但是您可以在重新启动之前保存和还原重要数据,然后在重新启动之后还原它,以使转换过程变得快速而轻松。

学习和实施它很可能会很耗时。

这是一个答案 ,对答案的第二部分有一些了解。

PS:我到处都使用“ .exe”作为参考。 试想一下它是关于罐子的,适用同样的原理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM