您是否可以卸载然后重新加载同一JAR的不同版本,这是第二个JAR的依赖,而无需重新加载第二个JAR?

时间:2015-12-08 10:53:33

标签: java jar classloader dependency-management

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

某些JAR依赖于其他JARS。在某些情况下,有多个JAR(Say, Set A )依赖于相同的单独JAR(让我们称之为 BaseJar )。出于这个原因,我有一个单独的文件夹用于这个 BaseJar ,所以我可以只加载一次,而不是有多个可以存在JAR的地方。

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

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

我知道如果我尝试在升级过程中使用该插件,可能会出现问题,JVM不再加载它尝试使用的类因此在加载较新版本之前无法使用。只是 这个新课程上传之后,是否会引发解决问题?

1 个答案:

答案 0 :(得分:0)

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?