在运行时更新 JAR

2022-09-01 07:26:12

假设一个 jar 在 JVM 中运行,是否可以卸载当前正在运行的 Jar 并将其从系统中删除。下载新版本并使用与上一个 Jar 相同的名称重命名它,然后初始化新的 Jar,在 JVM 中创建 Jar 的无缝更新。是否可以指示 JVM 执行此操作?是否可以在 Jar 运行时对其进行更新?


答案 1

下载新版本并使用与上一个Jar相同的名称重命名它,然后初始化新的Jar,在JVM中创建Jar的无缝更新...是否可以在 Jar 运行时对其进行更新?

JAR 文件未“正在运行”,JVM 正在运行。您的JAR文件只包含类信息(又名字节码指令),使JVM能够完成有用的工作。在大多数情况下,JVM 实际上不会在您的 JAR 文件上放置系统锁,因此您可以将该文件替换为您的 hearts 内容。

当然,真正的问题是,一旦JVM加载了你的JAR,它就会愉快地携带它加载的内容,并且永远不会再从你的JAR文件中读取,无论你覆盖它多少次。这是缺省类装入器的行为,无法更改 - 但是正如其他人所指出的 - 您不必使用缺省类装入器。您可以实现自己的,类似于 Web 应用程序服务器使用的功能,以便从文件系统加载更新的 JAR。但需要注意的是,定义自己的类加载器被认为是一个“坏主意™”,除非你真的知道你在做什么。您可以在此处和此处阅读更多内容


答案 2

这是我以前见过很多次的事情(也是我自己也做过的)。我列出了可能出现的问题/解决方案的一些要点。

  • 如果 JVM 覆盖了稍后将使用的 JAR 文件,它将崩溃并转储。
    • 后来我的意思是类加载得非常懒惰,有些可能只会在程序的后期加载。
    • JVM 具有 JAR 文件的打开句柄,当 JAR 和指针出错时,库将失败
    • 通过从 JAR 文件预加载所有类和资源,可以降低概率
    • 如果您有自定义类装入器,则可以自己关闭句柄。
  • 您需要了解如何完成类加载。最好是控制。
    • 一个自定义类加载器,它将为每个 JAR 创建一个类加载器并管理版本控制
    • 了解您的应用程序如何使用类装入器以及它如何在新的 JAR 上运行(例如,检查 Tomcat 在覆盖 WAR 归档文件时执行的操作)
  • 在Windows上,您的JAR文件将被锁定,您无法覆盖它们。如果您处于控制之下,则可以在使用后解锁它们(关闭它们)。对于第三方系统,您必须找到相应的标志。例如,您可以在Tomcat上下文配置中检查反JARLocking
  • 总是最好避免覆盖同一文件,而是进行一些版本控制

总而言之,当您想要实现 JAR 重新加载时,可能会遇到许多问题。幸运的是,有一些方法可以最大限度地降低风险。最安全的方法是做类似的事情来获得相同的效果。最干净的是自定义类装入器和 JAR 文件版本控制。


推荐