将发布合并到一个 JAR 文件中的最简单方法
Posted
技术标签:
【中文标题】将发布合并到一个 JAR 文件中的最简单方法【英文标题】:Easiest way to merge a release into one JAR file 【发布时间】:2010-09-10 00:33:54 【问题描述】:是否有工具或脚本可以轻松地将一堆 JAR 文件合并到一个 JAR 文件中?一个好处是可以轻松设置主文件清单并使其可执行。
具体案例是Java restructured text tool。我想用类似的东西来运行它:
java -jar rst.jar
据我所知,它没有依赖关系,这表明它不应该是一个简单的单文件工具,但下载的 ZIP 文件包含很多库。
0 11-30-07 10:01 jrst-0.8.1/
922 11-30-07 09:53 jrst-0.8.1/jrst.bat
898 11-30-07 09:53 jrst-0.8.1/jrst.sh
2675 11-30-07 09:42 jrst-0.8.1/readmeEN.txt
108821 11-30-07 09:59 jrst-0.8.1/jrst-0.8.1.jar
2675 11-30-07 09:42 jrst-0.8.1/readme.txt
0 11-30-07 10:01 jrst-0.8.1/lib/
81508 11-30-07 09:49 jrst-0.8.1/lib/batik-util-1.6-1.jar
2450757 11-30-07 09:49 jrst-0.8.1/lib/icu4j-2.6.1.jar
559366 11-30-07 09:49 jrst-0.8.1/lib/commons-collections-3.1.jar
83613 11-30-07 09:49 jrst-0.8.1/lib/commons-io-1.3.1.jar
207723 11-30-07 09:49 jrst-0.8.1/lib/commons-lang-2.1.jar
52915 11-30-07 09:49 jrst-0.8.1/lib/commons-logging-1.1.jar
260172 11-30-07 09:49 jrst-0.8.1/lib/commons-primitives-1.0.jar
313898 11-30-07 09:49 jrst-0.8.1/lib/dom4j-1.6.1.jar
1994150 11-30-07 09:49 jrst-0.8.1/lib/fop-0.93-jdk15.jar
55147 11-30-07 09:49 jrst-0.8.1/lib/activation-1.0.2.jar
355030 11-30-07 09:49 jrst-0.8.1/lib/mail-1.3.3.jar
77977 11-30-07 09:49 jrst-0.8.1/lib/servlet-api-2.3.jar
226915 11-30-07 09:49 jrst-0.8.1/lib/jaxen-1.1.1.jar
153253 11-30-07 09:49 jrst-0.8.1/lib/jdom-1.0.jar
50789 11-30-07 09:49 jrst-0.8.1/lib/jewelcli-0.41.jar
324952 11-30-07 09:49 jrst-0.8.1/lib/looks-1.2.2.jar
121070 11-30-07 09:49 jrst-0.8.1/lib/junit-3.8.1.jar
358085 11-30-07 09:49 jrst-0.8.1/lib/log4j-1.2.12.jar
72150 11-30-07 09:49 jrst-0.8.1/lib/logkit-1.0.1.jar
342897 11-30-07 09:49 jrst-0.8.1/lib/lutinwidget-0.9.jar
2160934 11-30-07 09:49 jrst-0.8.1/lib/docbook-xsl-nwalsh-1.71.1.jar
301249 11-30-07 09:49 jrst-0.8.1/lib/xmlgraphics-commons-1.1.jar
68610 11-30-07 09:49 jrst-0.8.1/lib/sdoc-0.5.0-beta.jar
3149655 11-30-07 09:49 jrst-0.8.1/lib/xalan-2.6.0.jar
1010675 11-30-07 09:49 jrst-0.8.1/lib/xercesImpl-2.6.2.jar
194205 11-30-07 09:49 jrst-0.8.1/lib/xml-apis-1.3.02.jar
78440 11-30-07 09:49 jrst-0.8.1/lib/xmlParserAPIs-2.0.2.jar
86249 11-30-07 09:49 jrst-0.8.1/lib/xmlunit-1.1.jar
108874 11-30-07 09:49 jrst-0.8.1/lib/xom-1.0.jar
63966 11-30-07 09:49 jrst-0.8.1/lib/avalon-framework-4.1.3.jar
138228 11-30-07 09:49 jrst-0.8.1/lib/batik-gui-util-1.6-1.jar
216394 11-30-07 09:49 jrst-0.8.1/lib/l2fprod-common-0.1.jar
121689 11-30-07 09:49 jrst-0.8.1/lib/lutinutil-0.26.jar
76687 11-30-07 09:49 jrst-0.8.1/lib/batik-ext-1.6-1.jar
124724 11-30-07 09:49 jrst-0.8.1/lib/xmlParserAPIs-2.6.2.jar
如您所见,不需要手动执行此操作在某种程度上是可取的。
到目前为止,我只尝试过 AutoJar 和 ProGuard,它们都相当容易上手。 JAR 文件中的常量池似乎存在一些问题。
显然 jrst 有点坏了,所以我会修复它。 Maven pom.xml
文件显然也被破坏了,所以我必须在修复 jrst 之前修复它......我觉得自己像一个错误磁铁:-)
更新:我一直没有时间修复这个应用程序,但我查看了Eclipse 的“可运行 JAR 导出向导”,它基于一个胖 JAR。我发现这很容易用于部署我自己的代码。
其他一些优秀的建议可能更适合在非 Eclipse 环境中构建,oss 可能应该使用Ant 构建一个不错的构建。 (Maven,到目前为止只是让我感到痛苦,但其他人喜欢它。)
【问题讨论】:
One-Jar Fat Jar Eclipse Plugin jdotsoft.com/JarClassLoader.php 【参考方案1】:Ant 的 zipfileset
完成这项工作
<jar id="files" jarfile="all.jar">
<zipfileset src="first.jar" includes="**/*.java **/*.class"/>
<zipfileset src="second.jar" includes="**/*.java **/*.class"/>
</jar>
【讨论】:
+1 因为这也允许添加Eclipse 3.4 JDT 的 Runnable JAR 导出向导。
在 Eclipse 3.5 中,这已被扩展。现在您可以选择如何处理引用的 JAR 文件。
【讨论】:
能否检查生成的ant脚本是否可用?之前有一个绝对文件路径而不是相对文件路径的问题。【参考方案3】:尝试了几种不同的解决方案后,我发现One-JAR 最容易使用,并且成功地做到了这一点:生成一个包含我需要的所有内容的单个可执行 JAR。
One-JAR 使用自定义类加载器,可以导航嵌套资源。查看下载中的.bat文件,看起来jrst-0.8.1.jar中的org.codelutin.jrst.JRST是主类,所以你的manifest应该是这样的:
Main-Class: com.simontuffs.onejar.Boot
One-Jar-Main-Class: org.codelutin.jrst.JRST
真正酷的是 One-JAR 将为您处理命令行参数的传递。类路径由自定义类加载器处理,假设您需要的所有资源都捆绑到单个 JAR 中。
使用 One-JAR 最简单的方法是使用 ant;有一个自定义的“one-jar”ant 任务,其工作方式如下(假设您的清单称为“rst.mf”):
<target name="jar-rst">
<one-jar destfile="rst.jar" manifest="rst.mf">
<main jar="jrst-0.8.1.jar" />
<lib>
<fileset dir="$pathToJars">
<include name="batik-util-1.6-1.jar" />
<include name="icu4j-2.6.1.jar" />
<include name="commons-collections-3.1.jar" />
<!-- Snip -->
</fileset>
</lib>
</one-jar>
</target>
【讨论】:
one-jar 与 ant 的可脚本性使其可用于连续构建系统。 1.如果我的 jar 中有多个应用程序(几个入口点类),One-JAR 是否支持? 2. 如果这个jar被另一个应用程序使用了,它是否也可以使用“One-JAR”内嵌套jar中的类?【参考方案4】:如果您是Maven 用户,通常汇编插件会做您想做的事,或者可能是阴影插件,在某些情况下是组合。
使用程序集插件,您可以在项目中放置一个带有任何必要设置的清单文件,尽管默认值通常非常好。然后构建完成
mvn assembly:assembly
或者,如果您有更多特殊的事情要处理,可以选择其他目标之一。所有要包含的 JAR 文件都由 Maven 的依赖解析器拾取。如果您使用 shade 插件,它通常是安装目标的一部分,在我现在正在做的一个特定项目中,我会这样做
mvn install
mvn assembly:single
assembly:single
的目标是解决生命周期问题,在本例中是在 Spring 应用程序中。
【讨论】:
【参考方案5】:ProGuard 不仅可以将你的 JAR 文件打包成一个,还可以优化、清理或混淆你的类文件,使生成的 JAR 文件比之前所有 JAR 文件的总和小得多。
我实际上使用 JRST 工具尝试了 ProGuard,正如您所报告的那样。我试图追踪问题,发现它与 jrst 引用的 ICU4J 库中的a bug 相关。问题是,现在使用的 ICU 版本已经过时了。所以我用 ICU4J 3.2 版替换了icu.jar
文件。现在 ProGuard 发现了一堆关于 JRST 库不一致的其他错误/警告。
我的猜测是 ProGuard 按预期工作,但 jrst 的库并不一致。我不知道除了与它的开发人员交谈之外你还能做些什么,因为他们应该检查和更新项目的依赖关系。
【讨论】:
谢谢!我下载了它并尝试了,但是在这个特定的字段中,它在 icu4j-2.6.1.jar 上被未知的常量字段轰炸了,【参考方案6】:您可以使用JarJar,它将使用包阴影来确保您的 JAR 文件不会与其他文件冲突。
【讨论】:
【参考方案7】:(基于 Andrian 的):
<jar id="files" jarfile="all.jar">
<zipgroupfileset dir="$library.dir" includes="*.jar" excludes="test-helper.jar"/>
<zipfileset src="first.jar" includes="**/*.java **/*.class"/>
<zipfileset src="second.jar" includes="**/*.java **/*.class"/>
<fileset dir=".">
<include name="LICENSE"/>
<include name="NOTICE"/>
</fileset>
</jar>
【讨论】:
【参考方案8】:One-JAR 0.97 刚刚在http://one-jar.sourceforge.net 发布,并且已经扩展了对Spring 和Guice 等框架的支持,这可能会给其他方法带来麻烦。它还处理类加载器反转——其中一些 JAR 文件位于 One-JAR 外部(例如,JDBC 驱动程序可能未捆绑发货)。
One-JAR 是命令行,带有Ant 和Maven 2 个插件。使用“jar”工具构建也很简单。
我还可以推荐 Eclipse Jar Exporter (Runnable),Ference Hechler 在上面写道:他非常出色地提出了一种包装一组 JAR 文件的简单方法。他和我在 One-JAR 上工作,但 Jar Exporter 基于不同的代码库。
【讨论】:
【参考方案9】:有一个名为 autojar 的工具会扫描您的字节码并使用它找到的类编译一个 .jar 文件,包括引用(导入)的类。
但并不总是适用于 Spring 之类的东西,您可以在其中指定配置中的类名并由框架加载。
【讨论】:
感谢您的指点,似乎这个特定应用程序中的一些 .jar 让我在完成这项工作时有些头疼。【参考方案10】:或者使用Maven组装插件(mvn assembly:assembly)
【讨论】:
【参考方案11】:我认为你这里需要的工具是JarSplice:http://ninjacave.com/jarsplice
它不需要需要 Ant 或 Maven,有自己的 GUI,使用起来很简单,完全按照你的要求做 --> 它合并了几个 jar 的内容文件合并到一个文件中(请注意它仍然需要添加自己的类加载器)。
【讨论】:
【参考方案12】:您应该使用 maven 着色插件来做到这一点。我经常使用maven构建独立的jar文件,它非常强大
查看更多:
http://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html
【讨论】:
【参考方案13】:听起来像 Apache Ant 就是你要找的东西。
【讨论】:
以上是关于将发布合并到一个 JAR 文件中的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章
将所有 memcached 密钥转储到文件中的最简单方法是啥?
将原始 .aac 文件包装到 .m4a 容器中的最简单方法是啥