Easiest way to merge a release into one JAR file

79,428

Solution 1

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.

Solution 2

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>

Solution 3

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>

Solution 4

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.

Solution 5

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.

Share:
79,428
tovare
Author by

tovare

A programmer

Updated on July 05, 2022

Comments

  • tovare
    tovare almost 2 years

    Is there a tool or script which easily merges a bunch of JAR files into one JAR file? A bonus would be to easily set the main-file manifest and make it executable.

    The concrete case is a Java restructured text tool. I would like to run it with something like:

    java -jar rst.jar

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

          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 is somewhat desirable to not need to do this manually.

    So far I've only tried AutoJar and ProGuard, both of which were fairly easy to get running. It appears that there's some issue with the constant pool in the JAR files.

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


    Update: I never got around to fixing this application, but I checked out Eclipse's "Runnable JAR export wizard" which is based on a 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 environment, oss probably should make a nice build using Ant. (Maven, so far has just given me pain, but others love it.)

  • tovare
    tovare almost 16 years
    Thanks! i downloaded it and tried, but in this particluar field it bombed with unknown constant field on icu4j-2.6.1.jar,
  • matbrgz
    matbrgz over 14 years
    Could you check if the ant scripts generated are usable? There was an issue earlier with absolute filepaths instead of relative.
  • matbrgz
    matbrgz over 14 years
    The scriptability of one-jar with ant makes it usable in continuous build systems.
  • MRalwasser
    MRalwasser about 12 years
    1. Is One-JAR capable if there are several applications (several entry point classes) inside my jar? 2. What if this jar is used by another application, can it also use the classes in nested jars inside the "One-JAR"?
  • Shirkrin
    Shirkrin about 12 years
    +1 since this also allows one to add <manifest/> tags and set the main class.
  • Frans Lundberg
    Frans Lundberg over 10 years
    Would it be possible to do this for all jar files in a directory somehow. Would be very neat. Avoid need to update build.xml when libraries change.
  • Anupam Saini
    Anupam Saini over 10 years
    Try this approach you won't have to worry about addition of new jars: github.com/anupamsaini/Trie/blob/master/src/build.xml#L42