I’ve been working on a command line executable Java program. It’s in the testing phase, and packaging it up has proved a bit of an issue. The crux of this problem revolves around the MANY dependencies my application has. My lib folder (containing jars) is close on 500mb.
At the moment I have been using the Eclipse Runnable Jar Export wizard. Works flawlessly, except it has to be done from Eclipse. It generates a Jar about 500mb in size (don’t ask… suffice to say there need to be a lot of COBOL programs being packaged inside this program). This process takes <30s.
Ideally I would like this to be an Ant task of some kind, runnable via Jenkins and published to a repository. That way a user can just grab a Jar and run it.
Options I have investigated:
Custom classloader (FatJar, OneJar etc).
- Works
- Slow to execute at runtime as it’s required to unpack the jar.
- File structure is basically a Jar full of jars and the main class is delegated through the custom classloader.
-
Fast build time (5 mins)
<target name="hello" depends="compile"> <property name="classes.dir" value="onejar" /> <property name="build.dir" value="bin" /> <one-jar destfile="hello.jar"> <manifest> <attribute name="One-Jar-Main-Class" value="mainclass" /> <attribute name="Class-Path" value="." /> <attribute name="One-Jar-Show-Expand" value="true" /> </manifest> <main> <fileset dir="${build.dir}"/> </main> <lib> <fileset dir="lib"> <include name="**/*.jar"/> </fileset> </lib> </one-jar> </target>
Manually collecting dependencies, unpacking them into a folder, then jarring them all up with a custom MANIFEST file.
- Can’t get it to work
- LARGE (1500mb+)
-
Slow build time (20min +)
<target name="compile" depends="resolve"> <javac srcdir="src" destdir="bin" debug="true" deprecation="on"> <classpath> <path refid="ivy.path" /> </classpath> </javac> </target> <target name="jar" depends="compile" description="Create one big jarfile."> <jar jarfile="${dist}/deps.jar"> <zipgroupfileset dir="lib"> <include name="**/*.jar" /> </zipgroupfileset> </jar> <sleep seconds="1" /> <jar jarfile="${dist}/myjar.jar" basedir="bin"> <zipfileset src="${dist}/deps.jar" excludes="META-INF/*.SF" /> <manifest> <attribute name="Main-Class" value="mymainclassishere" /> </manifest> </jar> </target>
So yeah, does anyone have any suggestions? I am interested to hear peoples thoughts.
Edit: Specifically…. WHY the Eclipse Runnable Jar Export Wizard can export my Jar in less then 30s, yet my build times are > 30 minutes.
I know responding to your question can be frowned upon, but I did manage to solve this problem yesterday. Of all the options I tried I found the fastest solution was to replicate the Eclipse Runnable Jar Export Wizard. It requires the
jar-in-jar-loader.zipwhich can be acquired using the Runnable Jar Export Wizard… or you can find it via Google/Eclipse install.I found this solution was fast to build (30s) and much faster to run (5s bootup cost). It also left the jar structure very neat with no exploded jars.