Packaging & running in Java
JAR, executable JAR, classpath, jlink custom runtimes, jpackage.
What a JAR is
A JAR is a ZIP of class files plus **META-INF/MANIFEST.MF**. You can run any class in it by naming it on the classpath.
java -cp app.jar com.acme.MainExecutable JARs
Name the entry point in the manifest with **Main-Class** and the JAR becomes executable: java -jar app.jar. Without that entry, the launcher fails with "no main manifest attribute".
Manifest-Version: 1.0
Main-Class: com.acme.AppWriting Main-Class
Main-Class: com/acme/App.classA file path with .class: the launcher can't find the class.
Main-Class: com.acme.AppFully qualified class name, with dots and no .class suffix.
Where are my libraries?
You run java -cp "libs/*" -jar app.jar. Are the JARs in libs/ on the classpath?
No: with -jar, -cp and CLASSPATH are ignoredYes: -cp is always appliedOnly if they come first
Show the answer
No. In -jar mode the classpath is **the JAR itself plus the Class-Path entries in its manifest**. -cp and the CLASSPATH variable are ignored. A fat JAR or a manifest Class-Path solves it.
Slim runtimes and installers
jdeps shows which modules your code depends on. jlink builds a custom runtime containing only those modules. jpackage wraps your app and a runtime into a native installer (.msi, .dmg, .deb).
jdeps --print-module-deps app.jar
jlink --add-modules java.base,java.sql,\
java.logging --output runtimeShrinking a Docker image
The image ships a full JDK, but the app only uses java.base, java.sql and java.logging. A jlink runtime with just those modules drops the compiler, tools and unused libraries, usually a fraction of the original size.
Key takeaways
- Executable JAR: Main-Class entry in the manifest
- java -jar ignores -cp and CLASSPATH
- jlink: custom runtime with only the needed modules
- jpackage: .msi / .dmg / .deb installers
A JAR file really is a ZIP file: rename app.jar to app.zip and any unzip tool will open it.
Practice questions
Your Docker image with a full JDK is 400 MB, but the app only uses java.base, java.sql and java.logging. How can you shrink it?
- Delete rt.jar
- Run with -Xmx64m
- Use jlink to build a runtime containing just those modules
- Compress the JAR twice
Check your answer
Use jlink to build a runtime containing just those modules. jlink assembles a runtime image from only the modules you list, usually a fraction of a full JDK.
`java -jar app.jar` fails with "no main manifest attribute". What's missing?
- A public static void main in every class
- The -cp flag
- A module-info.java
- A Main-Class entry in META-INF/MANIFEST.MF
Check your answer
A Main-Class entry in META-INF/MANIFEST.MF. Without Main-Class the launcher doesn't know which class to start. Build plugins can add it for you.