I've heard people say that they create a fat JAR and deploy it. What do they actually mean ?
-
when you want to ship your product as jar you normally want to put classes in all dependent jars into one single big jar file. – nishu Oct 03 '13 at 04:34
-
@Nadeem_MK http://meta.stackexchange.com/questions/5280/embrace-the-non-googlers http://meta.stackexchange.com/questions/8724/how-should-we-deal-with-google-questions – eis Oct 03 '13 at 06:47
-
2The original answer was pointing to this link: http://www.javacodegeeks.com/2012/11/packing-your-java-application-as-one-or-fat-jar.html – George Stocker Oct 30 '14 at 10:46
-
3I wonder if a fat jar is the java equivalent of static linking in c – Sridhar Sarnobat Jul 23 '17 at 20:44
-
@SridharSarnobat Not quite. The "thin jar" is the equivalent of a statically linked C or C++ app. A "fat jar" includes the runtime but for a statically linked app, that of course is the underlying OS incl. syslibs. – Rob Wells Apr 21 '22 at 16:06
6 Answers
The different names are just ways of packaging Java applications.
Skinny – Contains only the bits you literally type into your code editor, and nothing else.
Thin – Contains all of the above plus the application’s direct dependencies of your application (db drivers, utility libraries, etc.).
Hollow – The inverse of thin. It contains only the bits needed to run your application but does not contain the application itself. Basically a pre-packaged “application server” to which you can later deploy your application, in the same style as traditional Java EE application servers, but with important differences.
Fat/Uber – Contains the bit you literally write yourself plus the direct dependencies of your application PLUS the bits needed to run your application “on its own”.
Source: Article from Dzone

- 30,738
- 21
- 105
- 131

- 2,785
- 2
- 16
- 31
-
17
-
1Wouldn't hollow be the inverse of skinny rather than thin? The inverse of thin would be none of your code and all the dependencies your code doesn't use. :-) – greymatter Oct 31 '19 at 17:02
-
-
The fat jar is the jar, which contains classes from all the libraries, on which your project depends and, of course, the classes of current project.
In different build systems fat jar is created differently, for example, in Gradle one would create it with (instruction):
task fatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.example.Main'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
In Maven it's being done this way (after setting up regular jar):
<pluginRepositories>
<pluginRepository>
<id>onejar-maven-plugin.googlecode.com</id>
<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>
</pluginRepositories>
<!-- ... -->
<plugin>
<groupid>org.dstovall</groupid>
<artifactid>onejar-maven-plugin</artifactid>
<version>1.4.4</version>
<executions>
<execution>
<configuration>
<onejarversion>0.97</onejarversion>
<classifier>onejar</classifier>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>

- 30,738
- 21
- 105
- 131

- 7,391
- 2
- 37
- 48
-
33
-
14
-
4Why use some third party plugin when there is maven assembly plugin with it's jar-with-dependencies assembly? – MeTTeO Apr 10 '16 at 07:23
-
3
-
3I think Uber-jar is a particular implementation of the bundling concept, whereas a fat jar is just the concept itself. – Sridhar Sarnobat Jul 10 '16 at 16:25
-
It's a bad idea to use fatJar in Gradle as you've described: like this, you will have tons of duplicate dependencies (if there are any). It's better to use proper plugin: https://github.com/johnrengelman/shadow – WhiteAngel Oct 17 '18 at 06:53
Fat jar or uber jar is a jar which contains all project class files and resources packed together with all it's dependencies. There are different methods for achieving such effect:
- dependencies' jars are copied into main jar and then loaded using special class loader (onejar, spring-boot-plugin:repackage)
- dependencies' jars are extracted at the top of main jar hierarchy (maven-assembly-plugin with it's jar-with-dependencies assembly)
- dependencies' jars are unpacked at the top of main jar hierarchy and their packages are renamed (maven-shade-plugin with shade goal)
Below sample assembly plugin configuration jar-with-dependencies:
<project>
<!-- ... -->
<build>
<!-- ... -->
<plugins>
<plugin>
<!-- NOTE: We don't need a groupId specification because the group is
org.apache.maven.plugins ...which is assumed by default.
-->
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<classifier>
</configuration>
<!-- ... -->
</project>
For more detailed explanation: Uber-JAR at imagej.net

- 30,738
- 21
- 105
- 131

- 2,088
- 16
- 19
-
2One thing to be careful about with FAT jars: conflicting versions of the same classes, across the different dependency jars. You can get really DIFFERENT (and often very frustrating-go-boom) effects depending on which approach you take (i.e. totally exploding all the jars and then reassembling them into one jar, vs. a jar-of-jars). Neither approach is necessarily better. Most build systems have some sort of "reverse dependency explorer" that can alert you to such version conflicts. – Charles Roth Feb 14 '19 at 18:51
-
Yes, unpacking multiple jars has some important drawbacks. Another one is the issue with META-INF files like signature files or SPI (services/package.Class) files which are overwritten by assembly plugin by default. Shade plugin has some special transformers which can merge the files if needed – MeTTeO Feb 12 '20 at 09:01
In the case of an executable jar, another way to think about a fat jar is one you can execute by invoking:
java -jar myFatLibrary.jar
without the need for -cp
/ --classpath
, or even double clicking the jar icon.

- 25,183
- 12
- 93
- 106
-
2Keep in mind that -jar requires Main-Class header in MANIFEST.MF: https://docs.oracle.com/javase/tutorial/deployment/jar/run.html – MeTTeO Aug 04 '17 at 06:28
-
1That's the case even for non-fat jars, so not relevant really. – Sridhar Sarnobat Aug 05 '17 at 22:05
-
-
By default it won't be fat. You have to explicitly use jar-with-dependencies, uberjar or shadow for mvn install to put anything other than your generated class files in there – Sridhar Sarnobat Jan 27 '19 at 20:10
From the Gradle documentation:
In the Java space, applications and their dependencies typically used to be packaged as separate JARs within a single distribution archive. That still happens, but there is another approach that is now common: placing the classes and resources of the dependencies directly into the application JAR, creating what is known as an uber or fat JAR.
Here is a demonstrated of uberJar
task in build.gradle
file:
task uberJar(type: Jar) {
archiveClassifier = 'uber'
from sourceSets.main.output
dependsOn configurations.runtimeClasspath
from {
configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
}
}
In this case, we’re taking the runtime dependencies of the project — configurations.runtimeClasspath.files
— and wrapping each of the JAR files with the zipTree()
method. The result is a collection of ZIP file trees, the contents of which are copied into the uber JAR alongside the application classes.

- 30,738
- 21
- 105
- 131

- 7,942
- 7
- 60
- 65
-
Copied content needs to be much more clearly marked as such. That is, quoted. – Peter Mortensen Jun 29 '23 at 19:26
-
See for example *"[How to reference material written by others](https://stackoverflow.com/help/referencing)"* – Peter Mortensen Jun 29 '23 at 21:03
-
Otherwise, [it is plagiarism](https://meta.stackoverflow.com/questions/329776/copy-paste-from-attached-tutorial). – Peter Mortensen Jun 29 '23 at 21:14
A fat jar simply contains same classes as a classical jar + classes from all of their runtime dependencies.
With Jeka ( https://jeka.dev) you can achieve it programmatically :
JkPathTreeSet.of(Paths.get("classes")).andZips(
Paths.get("bouncycastle-pgp-152.jar"),
Paths.get("classgraph-4.8.41.jar"),
Paths.get("ivy-2.4.0.jar")
).zipTo(Paths.get("fat.jar"));
or just by parametring Java plugin :
javaPlugin.getProject().getMaker().defineMainArtifactAsFatJar(true);

- 11
- 2