将发布合并到一个 JAR 文件中的最简单方法

是否有一个工具或脚本可以轻松地将一组 JAR文件合并到一个 JAR 文件中?额外的好处是可以轻松地设置主文件清单并使其可执行。

具体的例子是一个 Java 重构文本工具。我想用这样的东西来运行它:

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 文件中的常量池出现了一些问题。

显然只是有点坏了,我会尽力修好的。玛文 pom.xml文件显然也坏了,所以我必须在修复之前先修复它... ... 我觉得自己像个漏洞磁铁: -)


更新: 我一直没有修复这个应用程序,但是我查看了 日食的“ Runnable JAR export Wizard”,它是基于一个胖 JAR 的。我发现这对于部署我自己的代码来说非常容易使用。

其他一些优秀的建议可能更适合在非 Eclipse 环境中构建,oss 可能应该使用 蚂蚁构建一个不错的构建。(美芬,到目前为止只是给了我痛苦,但其他人喜欢它。)

80755 次浏览

If you are a Maven user, typically the assembly plugin do what you want, or potentially the shade plugin, and in some cases a combination.

With the assembly plugin you put a manifest file in your project with any necessary settings, although the defaults are usually quite good. Building is then done with

mvn assembly:assembly

Or if you have more special things to deal with, one of the other goals. All JAR files to include, are picked up by Maven's dependency resolver. If you use the shade plugin, it is typically part of the install goal, and in one particular project I'm doing now I do

mvn install
mvn assembly:single

The assembly:single goal is to work around lifetime issues, in this case in a Spring application.

Sounds like Apache Ant is what you're looking for.

There is a tool called autojar which will scan your bytecode and compile a .jar file with the classes it finds, including referenced (imported) classes.

Doesn't always work with something like Spring, though, where you specify the classnames in configuration and it gets loaded by the framework.

Eclipse 3.4 JDT's Runnable JAR export wizard.

In Eclipse 3.5, this has been extended. Now you can chose how you want to treat your referenced JAR files.

Having tried a few different solutions, I found One-JAR the easiest to work with, and have managed to make do exactly that: produce a single, executable JAR which contains everything I need.

One-JAR uses a custom class-loader which can navigate nested resources. Look at the .bat file in the download, it looks like org.codelutin.jrst.JRST in the jrst-0.8.1.jar is the main class, so your manifest should look like this:

Main-Class: com.simontuffs.onejar.Boot
One-Jar-Main-Class: org.codelutin.jrst.JRST

The really cool thing is that One-JAR will handle passing on command-line arguments for you. The classpath is handled by the custom class loader, assuming all the resources you need are bundled into the single JAR.

The easiest way to use One-JAR is with ant; there's a custom "one-jar" ant task which works as follows (assuming your manifest is called "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>

There is ProGuard which does not only pack your JAR files into one, but it can also optimize, cleanup or obfuscate your class files, making the resulting JAR file much smaller than the sum of all JAR files before.

I actually tried ProGuard with the JRST tool, and it is as you reported. I tried to track the problem down and found it to relate to a bug in the ICU4J library referenced by jrst. The problem is, that the used ICU version is far outdated right now. So I replaced the icu.jar file with ICU4J version 3.2. Now ProGuard finds a bunch of other errors/warnings about incosistencies with the libraries of JRST.

My guess is that ProGuard works as expected, but the libraries of jrst are just not consistent. I don't know if you can do much more than talk with its developers since they should check and update the dependencies of the project.

Or using the Maven assembly plugin (mvn assembly:assembly)

You can use JarJar which will use package shadowing to make sure your JAR file doesn't conflict with others.

Ant's zipfileset does the job

<jar id="files" jarfile="all.jar">
<zipfileset src="first.jar" includes="**/*.java **/*.class"/>
<zipfileset src="second.jar" includes="**/*.java **/*.class"/>
</jar>

One-JAR 0.97 has just been released at http://one-jar.sourceforge.net, and it has been extended wih support for frameworks such as Spring and Guice, which may present trouble to other approaches. It also handles classloader-inversion -- where some JAR files are external to the One-JAR (for example, JDBC drivers which may not be shipped bundled).

One-JAR is command-line, with Ant and Maven 2 plugins. It's also simple to build just using the "jar" tool.

I can also recommend the Eclipse Jar Exporter (Runnable) on which Ference Hechler wrote: he did a great job in coming up with a simple approach to wrapping a set of JAR files. He and I worked on One-JAR, but the Jar Exporter is based on a different codebase.

(based on Andrian's):

<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>

You should use maven shading plugin to do that. I often use maven to build standalone jar file and it's so powerful

See more:

http://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html

I think that the tool you need here is JarSplice: http://ninjacave.com/jarsplice

It does not require Ant or Maven, has its own GUI, it is straightforward to use and do exactly what you asked --> It Merges the content of several jar files into a single one (please note it still need to add its own classloader).