【问题标题】:Classpath including JAR within a JAR在 JAR 中包含 JAR 的类路径
【发布时间】:2010-09-16 01:06:37
【问题描述】:

是否可以指定包含另一个 JAR 文件中的 JAR 文件的 Java classpath

【问题讨论】:

    标签: java classpath


    【解决方案1】:

    不写你自己的类加载器。您可以将 jar 添加到 jar 的类路径中,但它们必须位于同一位置,而不是包含在主 jar 中。

    【讨论】:

      【解决方案2】:

      您需要构建自定义类加载器来执行此操作或构建支持此功能的第三方库。最好的办法是从运行时提取 jar 并将它们添加到类路径中(或者已经将它们添加到类路径中)。

      【讨论】:

        【解决方案3】:

        如果您尝试创建一个包含您的应用程序及其所需库的 jar,有两种方法(据我所知)可以做到这一点。第一个是One-Jar,它使用一个特殊的类加载器来允许jar 的嵌套。第二个是UberJar,(或Shade),将包含的库炸开,把所有的类放到顶层jar中。

        我还应该提到 UberJar 和 Shade 分别是 Maven1 和 Maven2 的插件。如下所述,您还可以使用组装插件(实际上它更强大,但更难正确配置)。

        【讨论】:

        • 5 年后,我们到了。看起来这仍然是真的。很伤心:(
        • 我现在知道的最好的方法是使用 IntelliJ jar 工件。它从依赖的 jar 中提取所有类并将它们放入您的一个 jar 中。
        • 这在某些情况下是不可能的,例如当您使用需要签名的 BouncyCastle 等 JCE 实现时
        • @BrainSlugs83 ...你想做什么?我认为 One-Jar 的类加载器和打包器仍然是在 Jar(用于 Java SE)项目中包含 Jar 的答案。使用 UberJar 通过将类文件提取到您的 Jar 中来消除问题。
        • UberJar 链接需要登录凭据。有后续网页吗?
        【解决方案4】:

        我正要建议提取同一级别的所有文件,然后从结果中制作一个 jar,因为包系统应该将它们整齐地分开。 那将是手动方式,我想史蒂夫指出的工具会很好地做到这一点。

        【讨论】:

          【解决方案5】:

          我将 maven 用于我的 java 构建,它有一个名为 maven assembly plugin 的插件。

          它可以满足您的要求,但就像其他一些建议所描述的那样 - 本质上是分解所有依赖的 jar 并将它们重新组合成一个 jar

          【讨论】:

          • Maven 程序集插件使用起来非常痛苦...... UberJar 和 Shade 是 Maven1 和 Maven2 插件(我应该在上面提到,现在会这样做)
          【解决方案6】:

          您不想使用那些“爆炸 JAR 内容”解决方案。它们肯定会让东西更难看(因为所有东西都在同一水平上爆炸)。此外,可能存在命名冲突(如果人们使用正确的包,则不会发生,但您不能总是控制这一点)。

          您想要的功能是top 25 Sun RFEs:RFE 4648386 之一,Sun 以其无限的智慧将其指定为低优先级。我们只能希望太阳醒来......

          与此同时,我遇到的最佳解决方案(我希望 Sun 将其复制到 JDK 中)是使用自定义类加载器 JarClassLoader

          【讨论】:

          • 命名冲突实际上几乎肯定会发生在 log4j 配置和许可证文本之类的东西上。
          • 遗憾的是,JarClassLoader 是 GPLv3/商业版,因此​​它可能不会“被 sun(现在是 oracle)复制”,并且不能用于商业用途,除非你有内部政治影响力和时间来获得一些东西购买。但是,我同意在当前目录中出现的 jars 是一件坏事。
          • +1 对于这个答案中的想法(尽管我不会对答案本身 +1):你不能重新打包任何签名的 JAR 文件,所以这种技术不能可以在很多情况下使用(例如Java的activation.jar)。
          【解决方案7】:

          使用 zipgroupfileset 标签(使用与 fileset 标签相同的属性);它将解压缩目录中的所有文件并添加到您的新存档文件中。 更多信息:http://ant.apache.org/manual/Tasks/zip.html

          这是解决 jar-in-a-jar 问题的一种非常有用的方法——我知道是因为我在试图弄清楚该怎么做时搜索了这个确切的 StackOverflow 问题。如果您想将一个 jar 或 jar 文件夹打包到您使用 Ant 构建的 jar 中,那么忘记所有这些类路径或第三方插件的东西,您所要做的就是(在 Ant 中):

          <jar destfile="your.jar" basedir="java/dir">
            ...
            <zipgroupfileset dir="dir/of/jars" />
          </jar>
          

          【讨论】:

            【解决方案8】:

            温斯顿很不错http://blog.jayway.com/2008/11/28/executable-war-with-winstone-maven-plugin/。但不适用于复杂的网站。这是一种耻辱,因为只需要包含插件。

            【讨论】:

              【解决方案9】:

              如果您使用 ant 构建(我使用的是 eclipse 中的 ant),您可以添加额外的 jar 文件 通过告诉蚂蚁添加它们... 如果您有一个由多人维护的项目,则不一定是最佳方法,但它适用于一个人的项目并且很容易。

              例如,我构建 .jar 文件的目标是:

              <jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
                  <manifest>
                      <attribute name="Author" value="ntg"/>
                      ................................
                      <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
                  </manifest>
              </jar>
              

              我只是添加了一行来实现它:

              <jar ....">
                  <zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
                  <manifest>
                      ................................
                  </manifest>
              </jar>
              

              在哪里

              <property name="external-lib-dir" 
                        value="C:\...\eclipseWorkspace\Filter\external\...\lib" />
              

              是带有外部罐子的目录。 就是这样……

              【讨论】:

                【解决方案10】:

                经过一些研究,我发现了不需要 maven 或任何 3rd 方扩展/程序的方法。

                您可以在清单文件中使用“Class-Path”。

                例如:

                创建清单文件 MANIFEST.MF

                Manifest-Version: 1.0
                Created-By: Bundle
                Class-Path: ./custom_lib.jar
                Main-Class: YourMainClass
                

                编译所有类并运行jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar

                c 代表创建存档 f 表示要指定文件 v 用于详细输入 m 表示我们将传递自定义清单文件

                确保您在 jar 包中包含 lib。你应该可以正常运行jar了。

                基于:http://www.ibm.com/developerworks/library/j-5things6/

                您需要的有关类路径的所有其他信息都找到here

                【讨论】:

                • 这个答案 not 工作。来自 oracle 文档(由上面的香蕉链接):“Class-Path 标头指向本地网络上的类或 JAR 文件,而不是 JAR 文件中的 JAR 文件”
                • 知道这是否也可以在 Android 设置中使用。
                • 它适用于可执行 jar 场景(已测试),但当您想在库 jar 中包含 jar 时,它可能不起作用。
                • 哦不,它不起作用,一旦我把custom_lib.jar 移走,jar 就不能再执行了:(
                • Class-Path中如何指定多个jar?
                【解决方案11】:

                好吧,如果您使用的是 Eclipse,那么有一个非常简单的方法。

                将您的项目导出为“可运行”Jar 文件(在 Eclipse 中右键单击项目文件夹,选择“导出...”)。配置导出设置时,请务必选择“将所需库提取到生成的 Jar 中”。请记住,选择“Extract...”和not“Package required libraries...”。

                另外:您必须在导出设置中选择运行配置。因此,您总是可以在某个类中创建一个空的 main() 并将其用于您的运行配置。

                无论如何,不​​能保证在 100% 的时间内工作 - 因为您会注意到一条弹出消息,告诉您确保检查您所使用的 Jar 文件的许可证包括关于不复制签名文件的内容。但是,我已经这样做了 ,从未遇到过问题。

                【讨论】:

                  【解决方案12】:

                  如果您有 eclpise IDE,您只需导出您的 JAR 并选择“将所需的库打包到生成的 JAR 中”。 eclipse 会自动将所需的依赖 JAR 添加到生成的 JAR 中,并生成一些自动加载这些 JAR 的 eclipse 自定义类加载器。

                  【讨论】:

                    【解决方案13】:

                    提取到 Uber-dir 对我有用,因为我们都应该使用 root:\java 并且在带有版本控制的包中包含 outlets 代码。即ca.tecreations-1.0.0。签名没问题,因为 jar 从其下载位置完好无损。 3rd 方签名完整,解压到 c:\java。这是我的项目目录。从启动器运行 java -cp c:\java Launcher

                    【讨论】:

                    • 所以 jars 在 c:\java\jars. c:\java 中的源代码、二进制文件和资源。排除备份、属性、keystore_private。解压到 c:\java 并使用类路径形成工具运行,所以可能是 ca.tecreations.system.tools.SystemTool 或类似的 java 类。执行那个。
                    • 我有工作代码供任何寻求解决此问题的人使用。请联系 tim.devries@yahoo.ca。我想我可以说,您可以尝试从 tecreations.ca/java/downloads/release/ 下载,然后尝试运行 ca.tecreations.launcher.Launcher,但 YMMV。
                    【解决方案14】:

                    如果您使用的是 Spring Boot,您可能需要查看以下文档:The Executable Jar Format

                    Java 不提供任何标准方式来加载嵌套的 jar 文件(即 即,jar 文件本身包含在 jar 中)。这可以是 如果您需要分发自包含应用程序,则会出现问题 无需解压即可从命令行运行。

                    为了解决这个问题,许多开发人员使用“阴影”罐子。一个有阴影的罐子 将所有 jar 中的所有类打包到一个“uber jar”中。这 带阴影的罐子的问题是很难看出哪个 库实际上在您的应用程序中。也可能有问题 如果在多个文件中使用相同的文件名(但内容不同) 罐子。 Spring Boot 采用了不同的方法,让您实际上 直接嵌套罐子

                    Spring 文档还列出了一些替代的单 Jar 解决方案

                    【讨论】:

                      猜你喜欢
                      • 2012-02-15
                      • 2023-03-18
                      • 1970-01-01
                      • 2016-09-04
                      • 2023-03-11
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多