rgoussu@goussu: ~/library/java/jdk-and-tools
~/library/java/jdk-and-tools cat jlink.md

jlink — custom runtime images

# Assembles a trimmed, self-contained Java runtime from a set of modules, replacing the standalone JRE for application distribution.

Conceptsaved 2026-08-09 #java#jvm#tooling#modules#packaging

Overview

jlink (since Java 9, JEP 282) links a set of JPMS modules — your application's plus the java.*/jdk.* modules it needs — into a self-contained runtime image with its own bin/java. It is the reason Oracle stopped shipping a standalone JRE: instead of "install Java, then the app", you ship one directory containing exactly the runtime your app requires, typically 30–70 MB instead of a full ~300 MB JDK. It is the standard base for slim container images and the runtime that jpackage bundles into installers.

Key points

  • Input: a module path (--module-path) of modular jars and/or jmods, plus --add-modules naming the roots; jlink resolves the transitive closure and drops everything else.
  • Discovering the module set: run jdeps --print-module-deps on your classpath first and feed the resulting list to --add-modules — the canonical two-step for non-trivial apps.
  • Size trimming: --strip-debug (removes debug symbols), --compress zip-6 (zip levels; older releases used --compress=2), --no-header-files, --no-man-pages.
  • Launchers: --launcher myapp=my.module/my.pkg.Main generates a start script in bin/.
  • Cross-linking: point --module-path at another platform's jmods to build, e.g., a Linux runtime image on macOS — jmods are what make this possible.
  • Non-modular apps: jlink links modules only. A classpath application can still benefit — build a runtime of just the JDK modules it needs (via jdeps) and run the app on the classpath of that image; automatic modules cannot be linked because their dependencies are unknowable.
  • Not an obfuscator or AOT compiler: classes are stored in the lib/modules jimage in a faster-to-load form, but this is still bytecode run by a normal JVM.

Examples

jdeps --print-module-deps --ignore-missing-deps -cp 'libs/*' app.jar
# -> java.base,java.net.http,java.sql

jlink --module-path $JAVA_HOME/jmods \
      --add-modules java.base,java.net.http,java.sql \
      --strip-debug --no-header-files --no-man-pages --compress zip-6 \
      --output build/runtime
build/runtime/bin/java -cp 'app.jar:libs/*' com.example.Main

Related

  • JDK & tools — parent catalogue of the JDK toolchain.
  • jdeps — computes the module list jlink needs (--print-module-deps).
  • jmod — the link-time artefact format jlink consumes for JDK modules.
  • jpackage — wraps a jlink runtime image into a native installer.
  • Build ecosystem — where runtime-image creation slots into Maven/Gradle builds.