在运行时更新JAR

Jam*_*ore 26 java jvm classpath classloader

如果jar在JVM中运行,则可以卸载当前运行的Jar并将其从系统中删除.下载新版本并使用与最后一个Jar相同的名称重命名,然后初始化新Jar,在JVM中创建Jar的无缝更新.甚至可以指示JVM执行此操作吗?甚至可以在运行时更新Jar吗?

Per*_*ion 27

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

JAR文件没有"运行",JVM正在运行.您的JAR文件只包含使JVM执行有用工作的类信息(也称为字节代码指令).在大多数情况下,JVM实际上不会对您的JAR文件进行系统锁定,因此您可以将该文件替换为您的内容.

真正的问题当然是,一旦JVM加载你的JAR,无论你多少次覆盖它,它都会愉快地携带你加载的内容并且再也不会从你的JAR文件中读取.这是默认的类加载器的行为,不能被改变-但正如其他人所指出的-你不必使用默认的类加载器.您可以实现自己的,类似于Web应用程序服务器使用的,以便从文件系统加载更新的JARS.但要注意的是 - 定义自己的类加载器被认为是'坏主意',除非你真的知道你在做什么.你可以在这里这里阅读更多.

  • 我们遇到了问题,我们在加载类后更新了jar,最终得到NoClassDefined错误.我猜测所请求的类没有被加载,当JVM试图这样做时,jar就不同了"被破坏". (4认同)
  • 仅供参考,Windows 7确实锁定了jar (3认同)

too*_*asr 24

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

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

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


Tho*_*sen 2

一般来说,你不能这样做,因为据我所知,这种行为没有正式定义。

但是,您可以使用官方类路径之外的jar 文件创建一个类加载器,然后根据需要从中加载类。通过丢弃类加载器加载的所有类实例,您可以删除当前资源,然后在新的 jar 文件上实例化新的类加载器,然后加载新类并创建新对象。

这非常复杂,所以也许您可以将 jar 制作为 OSGi 模块并通过 OSGi 加载器调用您的程序?