Java Language Creating an UberJAR for an application and its dependencies


Example

A common requirement for a Java application is that can be deployed by copying a single file. For simple applications that depend only on the standard Java SE class libraries, this requirement is satisfied by creating a JAR file containing all of the (compiled) application classes.

Things are not so straightforward if the application depends on third-party libraries. If you simply put dependency JAR files inside an application JAR, the standard Java class loader will not be able to find the library classes, and your application will not start. Instead, you need to create a single JAR file that contains the application classes and associated resources together with the dependency classes and resources. These need to be organized as a single namespace for the classloader to search.

The such a JAR file is often referred to as an UberJAR.

Creating an UberJAR using the "jar" command

The procedure for creating an UberJAR is straight-forward. (I will use Linux commands for simplicity. The commands should be identical for Mac OS, and similar for Windows.)

  1. Create a temporary directory, and change directory to it.

    $ mkdir tempDir
    $ cd tempDir
    
  2. For each dependent JAR file, in the reverse order that they need to appear on the application's classpath, used the jar command to unpack the JAR into the temporary directory.

    $ jar -xf <path/to/file.jar>
    

    Doing this for multiple JAR files will overlay contents of the JARs.

  3. Copy the application classes from the build tree into the temporary directory

    $ cp -r path/to/classes .
    
  4. Create the UberJAR from the contents of the temporary directory:

    $ jar -cf ../myApplication.jar
    

    If you are creating an executable JAR file, include an appropriate MANIFEST.MF as described here.

Creating an UberJAR using Maven

If your project is built using Maven, you can get it to create an UberJAR using either the "maven-assembly" or "maven-shade" plugins. See the Maven Assembly topic (in the Maven documentation) for details.

The advantages and drawbacks of UberJARs

Some of advantages of UberJARs are self-evident:

  • An UberJAR is easy to distribute.
  • You cannot break the library dependencies for an UberJAR, since the libraries are self-contained.

In addition, if you use an appropriate tooling to create the UberJAR, you will have the option of excluding library classes that are not used from the JAR file. However, that this is typically done by static analysis of the classes. If your application uses reflection, annotation processing and similar techniques, you need to be careful that classes are not excluded incorrectly.

UberJARs also have some disadvantages:

  • If you have lots of UberJARs with the same dependencies, then each one will contain a copy of the dependencies.
  • Some open source libraries have licenses which may preclude 1 their use in an UberJAR.

1 - Some open source library licenses allow you to use the library only of the end-user is able to replace one version of the library with another. UberJARs can make replacement of version dependencies difficult.