【问题标题】:Java Jar Combining several jars into one executable JarJava Jar 将几个 jar 组合成一个可执行的 Jar
【发布时间】:2013-04-04 15:36:55
【问题描述】:

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

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

【问题讨论】:

  • 好问题。我自己也曾多次想过这个问题。
  • 我也不知道,但刚才我搜索了一下,得到了一个链接:stackoverflow.com/questions/8312909/…。希望对你有帮助。
  • 感谢@TechnoCraft。我遇到了这篇文章,如答案中所述,Classloader 找不到嵌入式 jar。我想了解其中的原因。

标签: java executable-jar


【解决方案1】:

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

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

使用单个 jar 文件,随机访问是可能的,因为索引给出了文件系统偏移量,您可以查找每个偏移量并只读取您想要的文件

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

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

【讨论】:

  • 谢谢@Stephen。我只是想了解这不可能的原因。
【解决方案2】:

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

【讨论】:

  • 谢谢@Grim。我是否正确地说 Eclipse 的 Create Runnable Jar 选项将所有依赖项打包在一个 jar 中以及它自己的 jarinjar 加载器正在实现它自己的 ClassLoader?
  • 正确,见this question和相关答案。
【解决方案3】:

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

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

  • 允许嵌套多少?可以在 JAR 中包含 JAR 吗?
  • 如果一个类在两个 JAR 中,使用哪个?
  • 可以对 JAR 进行索引:该索引如何解释嵌套 JAR 的内容?

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2016-12-18
      • 1970-01-01
      • 2017-03-20
      • 2010-10-27
      • 1970-01-01
      • 2017-12-21
      • 1970-01-01
      • 2013-11-18
      • 2023-02-22
      相关资源
      最近更新 更多