Creating a JRE from the JDK with jlink

Since Java 9, the standard method to use a JRE, in case it is not available for your OS / architecture / package-format combination, is to create it from the existing JDK. The advantage of an JRE is the smaller filesystem footprint of 100 - 200MB less than a JDK.

The tool to create the JRE from the JDK is jlink, which is part of the JDK.

To demonstrate the use of jlink, here an example script for Java 11, 17 and 21 to produce a standard JRE:

#!/bin/bash

# origin JDK to create the JRE from and use the jlink tool from
JDK_HOME=/opt/zing/zing-jdk17

# destination directory where to write the generated JRE to, will be created
OUTJREDIR=jre

# comma separated list of additional tools to include in the JRE,
# The jdk.jcmd will add for example jcmd, jmap and other below $JAVA_HOME/bin
TOOLSMODULES=jdk.jcmd

# list of primarily JDK-modules, those will be excluded from the JRE
EXCLUDEMODULES=\
jdk.attach,\
jdk.compiler,\
jdk.editpad,\
jdk.internal.ed,\
jdk.internal.jvmstat,\
jdk.internal.le,\
jdk.internal.opt,\
jdk.jartool,\
jdk.javadoc,\
jdk.jcmd,\
jdk.jconsole,\
jdk.jdeps,\
jdk.jdi,\
jdk.jlink,\
jdk.jpackage,\
jdk.jshell,\
jdk.jstatd,\
jdk.unsupported.desktop,\
jdk.rmic,\
jdk.incubator

exclude=$(echo $EXCLUDEMODULES | sed 's/[, ]/\|/g')

jremodules=$($JDK_HOME/bin/java --list-modules | cut -d@ -f1 | sort | \
grep -E -v $exclude | paste -sd,)

test -d "$OUTJREDIR" && echo "canceled: directory $OUTJREDIR exists already." && exit 1

$JDK_HOME/bin/jlink --add-modules $jremodules,$TOOLSMODULES \
--save-opts $OUTJREDIR/jlink.log --strip-debug --compress 0 \
--no-header-files --no-man-pages --output $OUTJREDIR

chmod -R og-w $OUTJREDIR

# quick test on the generated JRE:
du -hs $OUTJREDIR
$OUTJREDIR/bin/java -version

Optionally, you can even reduce the JRE size further by removing modules which are not used by your application. That can be achieved by extending the list at EXCLUDEMODULES. The list of modules in your generated JRE is available with the following command to use as base for further optimizations:

$OUTJREDIR/bin/java --list-modules

But be aware of potential impacts the reduction below a standard JRE can have. If an application for example uses highly dynamic class loading, it may fail during uptime if the requested module is not included in your minimized JRE. Most of the missing modules will be immediately reported by an error message on start, but only those which are statically declared in the application source.

 

Add Comment

Comments

0 comments

Please sign in to leave a comment.

Was this article helpful?
0 out of 0 found this helpful