Is it possible to specify a Java classpath
that includes a JAR file contained within another JAR file?

- 8,576
- 33
- 117
- 202
15 Answers
If you're trying to create a single jar that contains your application and its required libraries, there are two ways (that I know of) to do that. The first is One-Jar, which uses a special classloader to allow the nesting of jars. The second is UberJar, (or Shade), which explodes the included libraries and puts all the classes in the top-level jar.
I should also mention that UberJar and Shade are plugins for Maven1 and Maven2 respectively. As mentioned below, you can also use the assembly plugin (which in reality is much more powerful, but much harder to properly configure).

- 6,002
- 1
- 28
- 38

- 5,663
- 1
- 24
- 34
-
87So here we are, 5 years later. It looks like this is still true. Very sad :( – T3rm1 Aug 06 '13 at 06:49
-
3The best way I know of now-a-days is to use IntelliJ jar artifact. It extracts all of the classes from the dependant jars and puts them in your one jar. – enl8enmentnow Jan 25 '14 at 17:50
-
3Thats not possible in some situations like when your using JCE implementations like BouncyCastle that needs to be signed – debuti Aug 11 '14 at 11:44
-
I know I've done this before -- years and years ago in Java 1.5 -- it didn't seem that hard then, just obscure. -- Now I need to re-figure out how I did that. -- Seems this isn't the answer I'm looking for. – BrainSlugs83 Oct 09 '14 at 08:40
-
1@BrainSlugs83 ... What are you trying to do? I think One-Jar's classloader and packager is still the answer to including a Jar within a Jar (for Java SE) projects. Using UberJar eliminates the problem by extracting class files into your Jar. – Steve Moyer Oct 14 '14 at 15:56
-
1The UberJar link needs login credentials. Is there any successor webpage? – Thomas Weller Aug 31 '15 at 09:51
-
@enl8enmentnow how can you do this in IntelliJ? – Stealth Rabbi Sep 28 '15 at 19:17
-
1@StealthRabbi This is how, it's pretty amazing for the rare times you need to do this: http://blog.jetbrains.com/idea/2010/08/quickly-create-jar-artifact/ – enl8enmentnow Sep 30 '15 at 03:44
-
Another +1 for One-Jar. Grab the ant-task distro and wire it into your builds. Takes 5 minutes and works as advertised. – Christopher Schultz Jun 28 '16 at 15:34
-
I happened to be working on a project where writing a script to do this was beneficial. It explodes all jars in a lib folder and puts them in with your top-level jar. Here's a gist of the script: https://gist.github.com/prmichaelsen/334c4928ba8d75cfbddecc048f070d13 – Patrick Michaelsen Aug 28 '17 at 00:02
-
@debuti how would one solve this problem when you do have bouncyCastle? – eugenevd Jun 29 '18 at 07:46
-
@T3rm1 so we are in 2020 and it is still true :( – Michael Chourdakis Feb 25 '20 at 07:16
-
SpringBoot fat jar are have jars inside the main jar. The key is to find to be able to reference a fat jar in a classpath... – Esteban Feb 25 '22 at 08:35
-
@MichaelChourdakis in 2022 I was able to do this in Eclipse -> project -> export -> runnable jar file -> lets you choose whether you want to include the jar (but you'll have to manually handle the classloader) or explode it (which worked for me) – unziberla May 04 '22 at 23:25
You do NOT want to use those "explode JAR contents" solutions. They definitely make it harder to see stuff (since everything is exploded at the same level). Furthermore, there could be naming conflicts (should not happen if people use proper packages, but you cannot always control this).
The feature that you want is one of the top 25 Sun RFEs: RFE 4648386, which Sun, in their infinite wisdom, has designated as being of low priority. We can only hope that Sun wakes up...
In the meanwhile, the best solution that I have come across (which I wish that Sun would copy in the JDK) is to use the custom class loader JarClassLoader.

- 11,186
- 8
- 79
- 110

- 539
- 4
- 2
-
4Naming conflicts are actually almost guaranteed to happen with stuff like log4j configuration and license texts. – Michael Borgwardt Oct 26 '11 at 16:00
-
1Sadly JarClassLoader is GPLv3/commercial so it's probably not going to get "copied by sun (now oracle)", and can't be used commercially unless you have the internal political clout and time to get something purchased. I agree however that jars that barf on the current directory are a bad thing. – Gus May 16 '14 at 18:56
-
+1 for the idea in this answer (though I won't be +1'ing the answer itself): you can't re-package any signed JAR file, so this technique can't be used in many situations (e.g. Java's `activation.jar`). – Christopher Schultz Jun 28 '16 at 15:35
After some research I have found method that doesn't require maven or any 3rd party extension/program.
You can use "Class-Path" in your manifest file.
For example:
Create manifest file MANIFEST.MF
Manifest-Version: 1.0
Created-By: Bundle
Class-Path: ./custom_lib.jar
Main-Class: YourMainClass
Compile all your classes and run jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar
c
stands for create archive
f
indicates that you want to specify file
v
is for verbose input
m
means that we will pass custom manifest file
Be sure that you included lib in jar package. You should be able to run jar in the normal way.
based on: http://www.ibm.com/developerworks/library/j-5things6/
all other information you need about the class-path do you find here
-
21This answer does *not* work. from the oracle doc (linked by banana above): "The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file" – sebnukem Jul 03 '15 at 20:41
-
-
3It works for executable jar scenario (tested), but it may not work when you want to include a jar in a library jar. – Cychih May 15 '16 at 07:07
-
5Oh no it doesn't work, once I moved `custom_lib.jar` away, the jar cannot be executed anymore :( – Cychih May 15 '16 at 07:27
-
-
-
As stated by @sebnukem above, it doesn't work. It'd be great if it did work, since then, you wouldn't have to use those OneJar and UberJar/Shade stuff or whatever. However, with the new `jpackage` introduced in JDK 14, you can create an installable package which will also include all libraries that you want. And using a `jar` file seems kind of primitive. – Tech Expert Wizard Nov 14 '20 at 15:47
Use the zipgroupfileset tag (uses same attributes as a fileset tag); it will unzip all files in the directory and add to your new archive file. More information: http://ant.apache.org/manual/Tasks/zip.html
This is a very useful way to get around the jar-in-a-jar problem -- I know because I have googled this exact StackOverflow question while trying to figure out what to do. If you want to package a jar or a folder of jars into your one built jar with Ant, then forget about all this classpath or third-party plugin stuff, all you gotta do is this (in Ant):
<jar destfile="your.jar" basedir="java/dir">
...
<zipgroupfileset dir="dir/of/jars" />
</jar>

- 11,246
- 21
- 71
- 120
If you are building with ant (I am using ant from eclipse), you can just add the extra jar files by saying to ant to add them... Not necessarily the best method if you have a project maintained by multiple people but it works for one person project and is easy.
for example my target that was building the .jar file was:
<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
<manifest>
<attribute name="Author" value="ntg"/>
................................
<attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
</manifest>
</jar>
I just added one line to make it:
<jar ....">
<zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
<manifest>
................................
</manifest>
</jar>
where
<property name="external-lib-dir"
value="C:\...\eclipseWorkspace\Filter\external\...\lib" />
was the dir with the external jars. And that's it...
Not without writing your own class loader. You can add jars to the jar's classpath, but they must be co-located, not contained in the main jar.

- 14,735
- 5
- 36
- 39
You need to build a custom class-loader to do this or a third-party library that supports this. Your best bet is to extract the jar from the runtime and add them to the classpath (or have them already added to the classpath).

- 17,844
- 7
- 51
- 64
I use maven for my java builds which has a plugin called the maven assembly plugin.
It does what your asking, but like some of the other suggestions describe - essentially exploding all the dependent jars and recombining them into a single jar

- 12,400
- 15
- 59
- 80
-
The Maven assembly plugin is pretty painful to use ... UberJar and Shade are Maven1 and Maven2 plugins (a fact I should have mentioned above, and will do so now) – Steve Moyer Oct 08 '08 at 19:09
If you have eclpise IDE, you just need to export your JAR and choose "Package Required libraries into generated JAR". eclipse will automatically add the required dependant JARs into the generated JAR as well as generated some eclipse custom class loader that load these JARs automatically.

- 113
- 8
I was about to advise to extract all the files at the same level, then to make a jar out of the result, since the package system should keep them neatly separated. That would be the manual way, I suppose the tools indicated by Steve will do that nicely.

- 40,535
- 6
- 96
- 134
Well, there is a very easy way if you're using Eclipse.
Export your project as a "Runnable" Jar file (right-click project folder from within Eclipse, select "Export..."). When you configure the export settings, be sure to select "Extract required libraries into generated Jar." Keep in mind, select "Extract..." and not "Package required libraries...".
Additionally: You must select a run-configuration in your export settings. So, you could always create an empty main( ) in some class and use it for your run configuration.
Anyway, it isn't guaranteed to work 100% of the time - as you will notice a pop-up message telling you to make sure you check the licenses of the Jar files you're including and something about not copying signature files. However, I have been doing this for years and have never encountered a problem.

- 21
- 3
In case you are using Spring Boot, you may want to have a look at this documentation: The Executable Jar Format
Java does not provide any standard way to load nested jar files (that is, jar files that are themselves contained within a jar). This can be problematic if you need to distribute a self-contained application that can be run from the command line without unpacking.
To solve this problem, many developers use “shaded” jars. A shaded jar packages all classes, from all jars, into a single “uber jar”. The problem with shaded jars is that it becomes hard to see which libraries are actually in your application. It can also be problematic if the same filename is used (but with different content) in multiple jars. Spring Boot takes a different approach and lets you actually nest jars directly.
The Spring documentation also lists some alternative single Jar solutions:

- 4,782
- 5
- 27
- 40
Winstone is pretty good http://blog.jayway.com/2008/11/28/executable-war-with-winstone-maven-plugin/. But not for complex sites. And that's a shame because all it takes is to include the plugin.

- 2,913
- 4
- 35
- 48
Extracting into an Uber-dir works for me as we s should all be using root:\java and have outlets code in packages with versioning. Ie ca.tecreations-1.0.0. Signing is okay because the jars are intact from their downloaded location. 3rd party signatures intact, extract to c:\java. There’s my project dir. run from launcher so java -cp c:\java Launcher

- 1
- 2
-
So jars in c:\java\jars. Source, binaries and resources in c:\java. Exclude backups,properties, keystore_private. Unpack to c:\java and run with classpath forming tool, so maybe ca.tecreations.system.tools.SystemTool or comparable java class. Execute that. – Tim de Vries Nov 29 '19 at 00:56
-
I have working code for anyone seeking a solution to this problem. Please contact tim.devries@yahoo.ca. I guess I could say, you can attempt to download from tecreations.ca/java/downloads/release/ and then attempt to run ca.tecreations.launcher.Launcher, but YMMV. – Tim de Vries Jan 02 '22 at 03:24
I would advise to use one jar and many libraries in separate jars, not in a single jar. Use separate jar from jar libraries.
Suppose you have such a folder structure:
path/yourApp/yourApp.jar
path/yourApp/lib/lib1.jar
path/yourApp/lib/megalib1.jar
path/yourApp/lib/supermegalib1.jar
All you have to do, add each of used jar to your MANIFEST.MF.
Manifest-Version: 1.0
Main-Class: com.company.MyProgram
Class-Path: ./lib/lib1.jar ./lib/megalib1.jar ./lib/supermegalib1.jar
So, in the manifest, you grant usage to each library.
Single file "all in one jar" might be easier to share and distribute, but not significantly. It will not make your program easier to maintain, and will not make your program to run faster. It will not make significant hdd usage difference. Just distribute as zip and unpack where it needs to be deployed.

- 1,758
- 2
- 20
- 31