A JAR is abbreviated as Java ARchive, which is basically as the definition says it is a collection of your class files also with some meta data defined in META-INF/MANIFEST.MF, zipped into a single file

The manifest contains the location to the classpath dependencies, main class to run if your jar is to be an application.

Though Java is dynamically linked, due to JARs we can create a single uber jar if needed. There are a couple of ways of packing the JAR, depending on your use case

Different ways of packing the JAR

Skinny JAR

A skinny JAR contains only the class files from your project. The dependencies will have to be resolved and added in your classpath. When you are building a library this is probably what you should do

Thin JAR

A thin jar contains all your class files and the direct dependencies, but will not contain the runtime needed. An example would be your web apps WAR, which you add to your Tomacat or Java EE server

Hollow JAR

A hollow JAR is the opposite of your the thin JAR, containing only the runtime and not contaning the functional parts of the app

Fat JAR

A fat JAR contains everything your application needs, including the runtime. It becomes a simple thing of calling java -jar <file-name> to run your application

Summary

In general

  • Application - Thin Jar, Fat Jar
  • Frameworks, runtime - Hollow Jar
  • Libraries - Skinny Jar

Of course this isn’t a hard fast rule, we could have a hollow jar for a cli application and let the consumer change the version of some jars. An example would be liquibase, which has it’s JDBC drivers outside so you can change it with your own driver