【问题标题】:Java's classloader versus jars-within-jarsJava 的类加载器与 jars-within-jars
【发布时间】:2013-10-01 15:59:48
【问题描述】:

我们有一个可执行的 JAR 文件,有时包含其他 JAR 文件。 (整个事情依赖于其他四个下载的 JAR,它们骑在太空中部署的巨型海龟的背上。)在运行时,我们动态加载嵌套的 JAR 文件,执行以下操作:

// wearyingly verbose error handling elided

URL nestedURL = the_main_system_classloader.getResource("path/to/nested.jar");
File temp = File.createTempFile (....);
// copy out nestedURL contents into temp, byte for byte

URL tempURL = temp.toURI().toURL();
URLClassLoader loader = URLClassLoader.newInstance(new URL[]{ tempURL });
Class<?> clazz = loader.loadClass("com.example.foo.bar.baz.Thing");
Thing thing = (Thing) clazz.newInstance();
// do stuff with thing

这种技术以前在这里提出过;链接包括this onethis one。我们目前的代码工作......

...主要是。我真的很想找到一些方法来避免临时文件的创建和复制(以及最终的清理,因为众所周知,deleteOnExit is evil)。毕竟,在开始时获得的 URL 指向一个 JAR:

URL nestedURL = the_main_system_classloader.getResource("path/to/nested.jar");
// nestedURL.toString() at this point is
// "jar:file:/C:/full/path/to/the/executable.jar!/path/to/nested.jar"
URLClassLoader loader = URLClassLoader.newInstance(new URL[]{ nestedURL });
Class<?> clazz = loader.loadClass("com.example.foo.bar.baz.Thing");

但是 loadClass 会抛出 ClassNotFound。

URLClassLoader 不能处理这种 JAR-within-a-JAR 的情况吗?或者我是否需要对涉及的一个或多个路径(nestedURL 或传递给 loadClass 的字符串)做一些事情来完成这项工作?

【问题讨论】:

  • 我可能会用它来构建一个 jar - maven.apache.org/plugins/maven-shade-plugin/examples/…
  • 您是否尝试过 addUrl 到您的主类加载器然后正常加载该类?
  • @PaulGrime 不幸的是,许可只允许我们重新分发嵌套的 jar 文件,但不能解压/重新打包它们。
  • 嗯,也许一开始就解压一次,然后用更新的类路径运行其他代码是最好的方法。例如。一些代码通过调用getResource() 来做一些时髦的事情,我不确定在另一个jar 中的资源的URL 应该是什么。之后是否需要整理,还是可以作为安装 jar 分发并解包然后留下内容?
  • 这个页面列出了很多嵌套JAR类加载的资源:@​​987654325@

标签: java jar classloader


【解决方案1】:

AFAIK vanilla URLClassloader 无法处理它。

到目前为止,这就是你的答案。

除了您的解决方案,我知道还有另外两种可能性:

  1. 创建一个胖罐子(例如使用 Maven Shade)
  2. 创建一个自定义类加载器,但这是一项艰苦的工作。

【讨论】:

    猜你喜欢
    • 2011-09-30
    • 1970-01-01
    • 2016-03-15
    • 2011-11-20
    • 2018-12-14
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 2017-11-04
    相关资源
    最近更新 更多