3

我知道要组合几个 jar 并创建一个可执行 jar,如果我不想解压缩依赖的jar,我需要使用OneJar 之类的工具。OneJar 有自己的自定义类加载器,可以在关联的 jar 中找到所需的类并加载它们。

我的问题是:为什么默认的类加载器无法从附加的 jar 中加载类。是因为安全吗?在创建包含其他依赖 jar 的单个可执行 jar(无需解压缩它们)时,我希望能清楚地解释需要自定义类加载器的原因。谢谢,

4

4 回答 4

2

技术原因是 uri 规范jar: 不支持嵌套。

您可以编写一个 URI 处理程序来满足此需求,但是当您嵌套在每个 jar 文件中时,性能将开始受到影响。

使用单个 jar 文件,可以进行随机访问,因为索引提供了文件系统偏移量,您可以查找每个偏移量并仅读取您想要的文件

使用嵌套 jar,您可以查找内部 jar,但要从该 jar 中拉出文件,您必须先从外部解压缩内部 jar,然后才能查找。

如果您不想将 jar 文件提取到临时目录并从生成的类路径构建自己的类加载器,我会查看 OSGi 或 Maven Shade 插件提供的解决方案

于 2013-04-04T07:27:21.177 回答
1

除了其他答案(Stephen 的答案到目前为止更准确)之外,还要考虑 JVM 不会抢先探索可用的类路径条目,因此为了找到类com.foo.Bar它将查看类似的路径com/foo/Bar.class在类路径中列出的条目中。如果这个路径可能在一个嵌套的 jar 中(它本身没有在类路径声明中列出),为了找到所述路径,类加载器应该首先探索所有嵌套的 jar(在过程中解压缩它们)以便进行适当的查找.

于 2013-04-04T07:36:55.270 回答
0

我怀疑这个决定是出于安全性:如果任何东西通过嵌套或多或少地变得安全,那将是令人惊讶的。事实上,能够在我的 uber-JAR 中签署所有 JAR 作为一个整体并让它们都检查完整性作为验证我的 JAR 的一部分,这可能非常好。

我认为主要原因是性能和简单性。如果 JAR 可以嵌套,那么这些问题的答案应该是什么:

  • 允许嵌套多少?你可以在 JAR 中的 JAR 中拥有 JAR 吗?
  • 在一个类在两个 JAR 中的情况下,使用哪个?
  • JAR 可以被索引:该索引如何解释嵌套 JAR 的内容?

将 JAR 想象成共享库似乎是最直接的:它是一个很好的、打包的、索引的、签名的、扁平的、准备链接的包。值得注意的是 Unix .so 和 Windows .dll 也不允许嵌套,原因与我怀疑的大致相同。

旁注:通常不需要创建“uberjar”:您通常可以使用Class-Path主 JAR 清单中的字段来允许它拉入外部库。

于 2013-04-04T07:14:09.490 回答
0

您可以将您的应用程序需要的所有 jars 放在您的应用程序文件夹(例如 lib)中,并 java -cp lib/*.jar ...在主 jar 的清单 Class-Path 属性中使用或枚举所有 jars。

于 2013-04-04T07:26:23.517 回答