Skip to content

Commit 1178318

Browse files
committed
Single jar post.
1 parent ed1b45f commit 1178318

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

_posts/2015-12-20-single-jar.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
layout: post
3+
title: "Unified Jar"
4+
date: 2015-12-20 09:23:07
5+
categories: java jar
6+
---
7+
8+
Sometimes I have a little program built in some JVM language. Usually it's a
9+
simple command line utility, maybe something that tests database connectivity
10+
via a JDBC connection, a simple JMS utility or a utility analogous to ping but
11+
for UDP.
12+
13+
The point is, I want to make it easy to set it up and move it from machine to
14+
machine. I just want to run it from the command line and have it work.
15+
16+
But, it's got several code files, maybe a resource, and I used something for a
17+
network library, and a command line parsing library...
18+
19+
What I would like is a consolidated jar, one jar that has what is needed, it is
20+
configured so it can be run with `java -jar Util.jar`, and it will work.
21+
22+
Obviously, the build system should be responsible for producing the new
23+
consolidated artifact.
24+
25+
For the simplest version, where there are only code files, no jars, it's pretty
26+
straight forward:
27+
28+
{% highlight xml %}
29+
<target name="dist" depends="compile"
30+
description="generate the distribution" >
31+
<!-- Create the distribution directory -->
32+
<mkdir dir="${dist}"/>
33+
34+
<jar jarfile="${dist}/Util.jar" basedir="${build}">
35+
<manifest>
36+
<attribute name="Main-Class" value="Main"/>
37+
</manifest>
38+
</jar>
39+
</target>
40+
{% endhighlight %}
41+
42+
Next, say there I used some libraries, something for parsing command line parameters.
43+
44+
There are two basic approaches to this. One is to create a jar containing jars.
45+
A custom class loader that knows how to read jars from inside jars is required
46+
to make this work. There are a couple available tools that do this. Eclipse can
47+
do this through the GUI or [One Jar](http://one-jar.sourceforge.net/).
48+
49+
This repo covers (but does not necessarily advocate) a second approach.
50+
Unjarring the libraries and creating a new jar with all the classes from the
51+
compile and the libraries in a single jar.
52+
53+
Adding this line:
54+
55+
{% highlight xml %}
56+
<zipfileset src="lib/commons-cli-1.3.1.jar" includes="**/*.class"/>
57+
{% endhighlight %}
58+
59+
will unzip the library jar, extract the .class files and include them the new
60+
jar that is being created. In context it looks like this:
61+
62+
{% highlight xml %}
63+
<target name="dist" depends="compile">
64+
<mkdir dir="${dist}"/>
65+
66+
<jar jarfile="${dist}/util.jar" basedir="${classes}">
67+
<manifest>
68+
<attribute name="Main-Class" value="Main"/>
69+
</manifest>
70+
<zipfileset src="lib/commons-cli-1.3.1.jar" includes="**/*.class"/>
71+
</jar>
72+
</target>
73+
{% endhighlight %}
74+
75+
Now there is a single jar that contains all the dependencies necessary to run
76+
the program.
77+
78+
There is an additional evolution possible. On Unix style systems it is possible
79+
to create a single consolidated file that can be set executable.
80+
81+
By taking a simple bash script:
82+
83+
{% highlight bash %}
84+
#! /bin/bash
85+
86+
exec /usr/bin/java -jar $0 "$@"
87+
{% endhighlight %}
88+
89+
and munging that on the beginning of a jar file, the result is a file that will
90+
execute on its own, as long as there is a /usr/bin/java executable installed.
91+
92+
By adding these lines to the Ant task, a concatenated file with the script and
93+
jar will be created.
94+
95+
{% highlight xml %}
96+
<concat destfile="${build}/util" binary="yes">
97+
<filelist dir="src/main/bash" files="header.sh"/>
98+
<filelist dir="${dist}" files="util.jar"/>
99+
</concat>
100+
<chmod file="${build}/util" perm="ugo+x"/>
101+
{% endhighlight %}
102+
103+
A sample project is available
104+
[here](https://github.com/jacobsimpson/consolidated_jar/tree/ant-build).
105+

0 commit comments

Comments
 (0)