包含JAR中的JAR的类路径


134

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

Answers:


94

如果您试图创建一个包含应用程序及其所需库的jar,则有两种方法(我知道)。第一个是One-Jar,它使用特殊的类加载器来允许jar的嵌套。第二个是UberJar(或Shade),它会爆炸包含的库并将所有类放在顶级jar中。

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


81
五年后,我们到了。看起来这仍然是正确的。很伤心:(
T3rm1

3
我现在知道的最好方法是使用IntelliJ jar工件。它从依赖的jar中提取所有类,并将它们放入您的一个jar中。
enl8enmentnow 2014年

2
在某些情况下这是不可能的,例如当您使用需要签署的
BousonCastle之

1
@ BrainSlugs83 ...您要做什么?我认为One-Jar的类加载器和打包器仍然是将Jar包含在Jar(用于Java SE)项目中的答案。使用UberJar可以通过将类文件提取到Jar中来解决此问题。
史蒂夫·莫耶 Steve Moyer)2014年

1
UberJar链接需要登录凭证。是否有后续网页?
托马斯·韦勒2015年

50

您不想使用那些“分解JAR内容”解决方案。它们绝对使查看东西变得更加困难(因为所有内容都在同一级别爆炸)。此外,可能存在命名冲突(如果人们使用适当的软件包,则不会发生,但您不能始终对此进行控制)。

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

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


4
实际上几乎可以保证命名冲突会发生在诸如log4j配置和许可证文本之类的事件中。
Michael Borgwardt

1
可悲的是JarClassLoader是GPLv3 /商业版,因此​​它可能不会“被太阳(现在是甲骨文)复制”,并且除非有内部政治影响力和时间来购买东西,否则不能在商业上使用。但是,我同意当前目录中的barf jars是一件坏事。
2014年

对该答案中的想法+1(尽管我不会对答案本身+1):您无法重新打包任何已签名的JAR文件,因此该技术不能在很多情况下使用(例如Java的activation.jar)。
Christopher Schultz

31

经过研究,我发现不需要Maven或任何第三方扩展/程序的方法。

您可以在清单文件中使用“类路径”。

例如:

创建清单文件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代表create archive f表示您要指定文件 v用于冗长的输入, m表示我们将传递自定义清单文件

确保在jar包中包含lib。您应该能够以正常方式运行jar。

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

您需要了解的类路径中的所有其他信息你觉得这里


19
这个答案并不能正常工作。来自oracle doc(由上面的香蕉链接):“ Class-Path标头指向本地网络上的类或JAR文件,而不是JAR文件中的JAR文件”
sebnukem 2015年

知道是否也可以在Android设置中使用的任何信息。
Mostowski崩溃2015年

2
它适用于可执行jar场景(已测试),但是当您想在库jar中包含jar时,它可能无法工作。
Cychih

5
哦,不,它不起作用,一旦我custom_lib.jar移开,罐子就无法执行了:(
Cychih

如何在类路径中指定多个jar?
Abhishek Tiwari

22

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

这是解决jar-in-a-jar问题的一种非常有用的方法-我知道,因为我在尝试弄清楚该怎么做的同时,已经在这个Google StackOverflow问题上进行了搜索。如果您想将一个jar或jar的一个文件夹打包到一个用Ant构建的jar中,那么就不用理会所有这些类路径或第三方插件,您要做的就是(在Ant中):

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

8

如果您正在使用ant进行构建(我正在使用eclipse中的ant),则可以通过对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" />

是外部罐子的目录。就是这样...


6

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


2

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


2

我将maven用于我的Java构建,其中有一个名为maven程序集插件的插件

它确实满足您的要求,但是像其他一些建议所描述的一样-本质上分解了所有依赖的jar,并将它们重新组合到单个jar中


Maven程序集插件使用起来非常痛苦……UberJar和Shade是Maven1和Maven2插件(事实上我应该在上面提到过,现在将这样做)
Steve Moyer

2

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


1

我打算建议在同一级别提取所有文件,然后从结果中提取一个jar文件,因为打包系统应将它们整齐地分开。那将是手动方式,我想由史蒂夫(Steve)指示的工具可以很好地做到这一点。



1

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

将项目导出为“可运行”的Jar文件(在Eclipse中右键单击项目文件夹,选择“导出...”)。配置导出设置时,请确保选择“将所需的库提取到生成的Jar中”。请记住,选择“提取...”而不是 “打包所需的库...”。

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

无论如何,它不能保证 100%的时间都能正常工作-因为您会注意到一条弹出消息,提示您确保检查所包含的Jar文件的许可证以及有关不复制签名文件的信息。但是,我这样做已经很多年了,从未遇到过问题。


0

解压缩到Uber-dir对我有用,因为我们所有人都应该使用root:\ java,并且在带有版本控制的软件包中包含出口代码。即ca.tecreations-1.0.0。可以签名,因为罐子从其下载位置是完整的。第三方签名完整无缺,提取到c:\ java。这是我的项目目录。从启动器运行,因此java -cp c:\ java Launcher


因此jars在c:\ java \ jars中。c:\ java中的源代码,二进制文件和资源。排除备份,属性,keystore_private。解压缩到c:\ java并使用类路径形成工具运行,因此可能是ca.tecreations.system.tools.SystemTool或类似的Java类。执行。
蒂姆·德弗里斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.