【问题标题】:Can you unload and then reload a different version of the same JAR, which is a dependency of a second JAR, without reloading the second JAR?你可以卸载然后重新加载同一个 JAR 的不同版本,它是第二个 JAR 的依赖项,而不重新加载第二个 JAR?
【发布时间】:2016-03-13 06:16:02
【问题描述】:

我有一系列包含 JAR 文件的文件夹,这些 JAR 充当我主应用程序的插件。每个单独的 JAR 文件夹都使用自己的类加载器加载,因此该 JAR 文件夹可以独立于其他文件夹进行加载和卸载。

一些 JAR 依赖于其他 JARS。在某些情况下,有多个 JAR(例如,Set A)依赖于同一个单独的 JAR(我们称之为 BaseJar)。出于这个原因,我为这个 BaseJar 设置了一个单独的文件夹,这样我就可以只加载一次,而不会有多个地方可以存在 JAR。

我需要提供可以禁用这些 JAR 集合中的任何一个,然后重新加载的功能。因此,这些插件的任何小更新都可以即时完成,而无需禁用整个应用程序。这引出了我标题中的问题。如果我要卸载这个 BaseJar 类,以便可以更新它,有没有办法避免必须卸载并重新加载 SetAall /em> JAR 也是?我希望他们能够在新的依赖项被单独的类加载器加载后继续正常运行。


编辑:为了澄清我的立场,在给出了一些答案之后,我已经有了一个可以工作的自定义 JarClassLoader。目前我可以加载我所有的插件并卸载它们都很好。我需要知道我是否可以批量加载和卸载,而不影响其他 JAR,这些 JAR 可能使用另一个 JAR 中包含的某些类,该类在运行时升级。

我知道如果我尝试使用该插件升级过程中可能会出现问题,它尝试使用的类不再由 JVM 加载,因此在更新之前不可用版本已加载。刚刚这个新类上传之后,会不会导致解决问题?

【问题讨论】:

  • 所以你想重新发明 OSGi?

标签: java jar classloader dependency-management


【解决方案1】:

Jar 只包含类文件。这不是真正的依赖问题,而是

  • 1 加载你想要的JAR(你想要的类)的问题

  • 和2,卸载一个替换

  • 和3,然后从这些JAR中的类中管理对象

1 要加载和重新加载 JAR,请通过更改类路径来查看:Can I dynamically unload and reload (other versions of the same) JAR?

代码:

 // jarFile is the version of the jar you want to use/overwrite.

  URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();

    Method m = URLClassLoader.class.getDeclaredMethod("addURL", new  Class[]{URL.class});
    m.setAccessible(true);
    m.invoke(urlClassLoader, jarFile.toURI().toURL());
    String cp = System.getProperty("java.class.path");
    if (cp != null) {
        cp += File.pathSeparatorChar + jarFile.getCanonicalPath();
    } else {
        cp = jarFile.toURI().getPath();
    }
    System.setProperty("java.class.path", cp);

提防可能发生的事情:阅读:Why can't System.setProperty() change the classpath at runtime?

并阅读这些警告:Why can't System.setProperty() change the classpath at runtime?

如果你之前这样做是为了加载你想要的类,那没关系。

如果没有,那就更难了:

2 和 3:当您进行更改时,您不应该拥有“旧”类的对象,否则结果应该是不可预测的。摆脱它是你的程序和类加载器的责任。

看到这个,它建议为每个 Jar 创建自己的 ClassLoader

Unloading classes in java?

【讨论】:

  • 就实际加载和卸载 JAR 而言,我认为 Stackoverflow 上的资源已经非常清晰,并且我已经有了一个可以工作的 JarClassLoader。你说我的问题不是依赖,但它确实是。我已经加载和卸载了我的 JAR,我现在需要知道 JAR 是否可以解决其他 JAR 中的类文件的依赖关系,这些 JAR 被卸载然后重新加载到较新的版本。
  • @Seb 我说这真的不是依赖问题。如果您确切地知道其中的哪些 JAR 和类需要哪些其他 JAR/类,那么您应该通过加载好的逻辑在每个 JAR/类中实现您的依赖逻辑。
  • 是的,我意识到了这一点,我确实加载了它们。我的问题围绕着在我卸载然后加载另一个 JAR 使用的这个类的新修改版本之后,这个 JAR 是否能够解析对这个更新的类的访问?是否需要重新加载自己才能看到这个更新的类,或者是否在 JVM 中必要时会发生这种解析?
  • 另见:stackoverflow.com/questions/6105124/… - 它基于类(和包),而不是基于 JAR。这些载荷通常是独立的。
  • 嗯,我不关心同时运行同一个类的两个版本,但我想我可以看到你想要表达的观点。我的问题基本上可以简化为“如果一个类可以访问 JVM 中的另一个类,它何时以及如何解决”。但我也找不到这个问题的结论性答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
  • 2014-08-29
  • 2018-03-14
  • 1970-01-01
相关资源
最近更新 更多