views:

8766

answers:

13

Hi,

I wonder if someone knows of a tool or script which easily merges a bunch of jar-files into one .jar. A bonus would be to easily set the main-file manifest and make it executable.

The concrete case is a java restructured text tool: http://jrst.labs.libre-entreprise.org/en/user/functionality.html

I would like to run it with something like

java -jar rst.jar

As far as I can tell it no dependencies which indicates that it shouldn't be an easy single-file tool, but the downloaded zip-file contains a lot of libs.

       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

As you can see, it somewhat desirable, not having to dothis manually.

Thank you.


Thanks for all the answers. So far I've only tried AutoJar and ProGuard so far, both of which was fairly easy to get running. It appears that there's some issue with the constant pool in the jars.

I'll investigate further :-)


Apparently jrst is slightly broken, so I'll make a go of fixing it. The maven pom.xml was apparently broken too, so I'll have to fix that before fixing jrst ... I feel like a bug-magnet :-)


I never got around to fixing this application, but i checked out Eclipse's "Runnable JAR export wizard" which is based on fat jar. I found this very easy to use for deploying my own code.

Some of the other excellent suggestions might be better for builds in a non-eclipse enviroment, oss probably should make a nice build using ant. (Maven, so far has just given me pain, but others love it)

Thanks all.

+3  A: 

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 jars 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 workaround lifetime issues, in this case in a spring application.

larsivi
A: 

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

PaulF
+2  A: 

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.

Phill Sacre
Thanks for the pointer, it seems that some .jars in this particular application is giving me some headache getting this done.
tovare
+1  A: 

One-Jar

Stephen Denne
+4  A: 

Fat Jar Eclipse Plugin

Stephen Denne
+8  A: 

Eclipse 3.4 JDT's Runnable JAR export wizard

Edited to add: This has been extended in Eclipse 3.5. Now you can chose how you want to treat your referenced jars.

Stephen Denne
Could you check if the ant scripts generated are usable? There was an issue earlier with absolute filepaths instead of relative.
Thorbjørn Ravn Andersen
+11  A: 

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>
Ashley Mercer
The scriptability of one-jar with ant makes it usable in continuous build systems.
Thorbjørn Ravn Andersen
+2  A: 

There is ProGuard which does not only pack your jars into one, but can also optimize, cleanup or obfuscate your classfiles, making the resulting jar much smaller than the sum of all jars before.

UPDATE:

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

jrudolph
Thanks! i downloaded it and tried, but in this particluar field it bombed with unknown constant field on icu4j-2.6.1.jar,
tovare
Thanks for the investigation.
tovare
+2  A: 

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

+4  A: 

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

Steve g
+1 Interresting tool
tovare
+1. Easy to use and works great.
Eelco
how do i use this??
Dacto
+14  A: 

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>
Adrian
+1  A: 

http://www.jdotsoft.com/JarClassLoader.php

gorokhmn
+3  A: 

Better late than never? 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 jars are external to the One-JAR (e.g. JDBC drivers which may not be shipped bundled).

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

I can also recommend the Eclipse Jar Exporter (Runnable) 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.

simontuffs
+1 for One-JAR ....
gareth_bowles