是否可以指定包含另一个JAR文件中包含的JAR文件的Java classpath
?
答案 0 :(得分:91)
如果您正在尝试创建包含应用程序及其所需库的单个jar,则有两种方法(我知道)可以执行此操作。第一个是One-Jar,它使用特殊的类加载器来允许嵌套jar。第二个是UberJar,(或Shade),它会爆炸包含的库并将所有类放在顶级jar中。
我还应该提到UberJar和Shade分别是Maven1和Maven2的插件。如下所述,您还可以使用程序集插件(实际上它更强大,但更难以正确配置)。
答案 1 :(得分:50)
您不想使用那些“爆炸JAR内容”解决方案。他们肯定会更难看到东西(因为一切都在同一水平爆炸)。此外,可能存在命名冲突(如果人们使用正确的软件包,则不应该发生,但您无法始终控制此情况。)
你想要的功能是top 25 Sun RFEs:RFE 4648386之一,Sun以其无限的智慧指定为低优先级。我们只能希望Sun醒来......
与此同时,我遇到的最佳解决方案(我希望Sun将在JDK中复制)是使用自定义类加载器JarClassLoader。
答案 2 :(得分:29)
经过一些研究后,我找到了不需要maven或任何第三方扩展/程序的方法。
您可以在清单文件中使用“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
答案 3 :(得分:22)
使用 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>
答案 4 :(得分:8)
如果你正在用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" />
是外部罐子的目录。 就是这样......
答案 5 :(得分:6)
不是没有编写自己的类加载器。您可以将jar添加到jar的类路径中,但它们必须位于同一位置,而不是包含在主jar中。
答案 6 :(得分:2)
您需要构建一个自定义类加载器来执行此操作或构建支持此操作的第三方库。最好的办法是从运行时中提取jar并将它们添加到类路径中(或者将它们添加到类路径中)。
答案 7 :(得分:2)
我在我的java版本中使用maven,它有一个名为maven assembly plugin的插件。
它可以满足您的要求,但就像其他一些建议所描述的那样 - 基本上爆炸所有相关的罐子并将它们重新组合成一个罐子
答案 8 :(得分:2)
如果你有eclpise IDE,你只需要导出你的JAR并选择“将所需的包打包到生成的JAR中”。 eclipse会自动将所需的依赖JAR添加到生成的JAR中,并生成一些自动加载这些JAR的eclipse自定义类加载器。
答案 9 :(得分:1)
我打算建议在同一级别提取所有文件,然后从结果中制作一个jar,因为包系统应该将它们整齐地分开。 这将是手动的方式,我想史蒂夫指出的工具会很好地做到这一点。
答案 10 :(得分:1)
Winstone非常好http://blog.jayway.com/2008/11/28/executable-war-with-winstone-maven-plugin/。但不适用于复杂的网站。这是一种耻辱,因为所需要的只是包含插件。
答案 11 :(得分:1)
嗯,如果您使用Eclipse,有一种非常简单的方法。
将项目导出为“Runnable”Jar文件(在Eclipse中右键单击项目文件夹,选择“Export ...”)。配置导出设置时,请务必选择“将所需的库提取到生成的Jar中”。请注意,选择“Extract ...”和 not “Package required libraries ...”。
另外:您必须在导出设置中选择运行配置。因此,您总是可以在某个类中创建一个空的main()并将其用于运行配置。
无论如何,它不是保证在100%的时间内工作 - 因为你会注意到一条弹出消息告诉你要确保你检查Jar文件的许可证你是包括和不复制签名文件的东西。但是,我一直这样做年并且从未遇到过问题。
答案 12 :(得分:0)
解压缩到Uber-dir对我有用,因为我们所有人都应使用root:\ java并在带有版本控制的软件包中包含出口代码。即ca.tecreations-1.0.0。可以签名,因为罐子从其下载位置是完整的。第三方签名完整无缺,提取到c:\ java。这是我的项目目录。从启动器运行,因此java -cp c:\ java Launcher
答案 13 :(得分:0)
如果您使用的是 Spring Boot,您可能需要查看此文档:The Executable Jar Format
<块引用>Java 不提供任何标准方式来加载嵌套的 jar 文件(即 即,本身包含在 jar 中的 jar 文件)。这可以是 如果您需要分发自包含的应用程序,则有问题 无需解包即可从命令行运行。
为了解决这个问题,许多开发人员使用“阴影”jar。一个有阴影的罐子 将所有 jars 中的所有类打包到一个“uber jar”中。这 阴影罐的问题是很难看出哪个 库实际上在您的应用程序中。它也可能有问题 如果在多个文件中使用相同的文件名(但具有不同的内容) 罐子。 Spring Boot 采用了不同的方法,让您实际上 直接嵌套罐子。
Spring 文档还列出了一些替代的单 Jar 解决方案: