Chapter 2. Creating a custom Java runtime environment for non-modular applications
You can create a custom Java runtime environment from a non-modular application by using the jlink
tool.
Prerequisites
Install Installing Red Hat build of OpenJDK on RHEL using an archive.
NoteFor best results, use portable Red Hat binaries as a basis for a Jlink runtime, because these binaries contain bundled libraries.
Procedure
Create a simple Hello World application by using the
Logger
class.Check the base Red Hat build of OpenJDK 17 binary exists in the
jdk-17
folder:Copy to Clipboard Copied! Toggle word wrap Toggle overflow ls jdk-17 ./jdk-17/bin/java -version
$ ls jdk-17 bin conf demo include jmods legal lib man NEWS release $ ./jdk-17/bin/java -version openjdk version "17.0.10" 2021-01-19 LTS OpenJDK Runtime Environment 18.9 (build 17.0.10+9-LTS) OpenJDK 64-Bit Server VM 18.9 (build 17.0.10+9-LTS, mixed mode)
Create a directory for your application:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow mkdir -p hello-example/sample
$ mkdir -p hello-example/sample
Create
hello-example/sample/HelloWorld.java
file with the following content:Copy to Clipboard Copied! Toggle word wrap Toggle overflow package sample; import java.util.logging.Logger; public class HelloWorld { private static final Logger LOG = Logger.getLogger(HelloWorld.class.getName()); public static void main(String[] args) { LOG.info("Hello World!"); } }
package sample; import java.util.logging.Logger; public class HelloWorld { private static final Logger LOG = Logger.getLogger(HelloWorld.class.getName()); public static void main(String[] args) { LOG.info("Hello World!"); } }
Compile your application:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow ./jdk-17/bin/javac -d . $(find hello-example -name \*.java)
$ ./jdk-17/bin/javac -d . $(find hello-example -name \*.java)
Run your application without a custom JRE:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow ./jdk-17/bin/java sample.HelloWorld
$ ./jdk-17/bin/java sample.HelloWorld Mar 09, 2021 10:48:59 AM sample.HelloWorld main INFO: Hello World!
The previous example shows the base Red Hat build of OpenJDK requiring 311 MB to run a single class.
(Optional) You can inspect the Red Hat build of OpenJDK and see many non-required modules for your application:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow du -sh jdk-17/
$ du -sh jdk-17/ 313M jdk-17/
Copy to Clipboard Copied! Toggle word wrap Toggle overflow ./jdk-17/bin/java --list-modules
$ ./jdk-17/bin/java --list-modules java.base@17.0.1 java.compiler@17.0.1 java.datatransfer@17.0.1 java.desktop@17.0.1 java.instrument@17.0.1 java.logging@17.0.1 java.management@17.0.1 java.management.rmi@17.0.1 java.naming@17.0.1 java.net.http@17.0.1 java.prefs@17.0.1 java.rmi@17.0.1 java.scripting@17.0.1 java.se@17.0.1 java.security.jgss@17.0.1 java.security.sasl@17.0.1 java.smartcardio@17.0.1 java.sql@17.0.1 java.sql.rowset@17.0.1 java.transaction.xa@17.0.1 java.xml@17.0.1 java.xml.crypto@17.0.1 jdk.accessibility@17.0.1 jdk.attach@17.0.1 jdk.charsets@17.0.1 jdk.compiler@17.0.1 jdk.crypto.cryptoki@17.0.1 jdk.crypto.ec@17.0.1 jdk.dynalink@17.0.1 jdk.editpad@17.0.1 jdk.hotspot.agent@17.0.1 jdk.httpserver@17.0.1 jdk.incubator.foreign@17.0.1 jdk.incubator.vector@17.0.1 jdk.internal.ed@17.0.1 jdk.internal.jvmstat@17.0.1 jdk.internal.le@17.0.1 jdk.internal.opt@17.0.1 jdk.internal.vm.ci@17.0.1 jdk.internal.vm.compiler@17.0.1 jdk.internal.vm.compiler.management@17.0.1 jdk.jartool@17.0.1 jdk.javadoc@17.0.1 jdk.jcmd@17.0.1 jdk.jconsole@17.0.1 jdk.jdeps@17.0.1 jdk.jdi@17.0.1 jdk.jdwp.agent@17.0.1 jdk.jfr@17.0.1 jdk.jlink@17.0.1 jdk.jpackage@17.0.1 jdk.jshell@17.0.1 jdk.jsobject@17.0.1 jdk.jstatd@17.0.1 jdk.localedata@17.0.1 jdk.management@17.0.1 jdk.management.agent@17.0.1 jdk.management.jfr@17.0.1 jdk.naming.dns@17.0.1 jdk.naming.rmi@17.0.1 jdk.net@17.0.1 jdk.nio.mapmode@17.0.1 jdk.random@17.0.1 jdk.sctp@17.0.1 jdk.security.auth@17.0.1 jdk.security.jgss@17.0.1 jdk.unsupported@17.0.1 jdk.unsupported.desktop@17.0.1 jdk.xml.dom@17.0.1 jdk.zipfs@17.0.1
This sample
Hello World
application has very few dependencies. You can use jlink to create custom runtime images for your application. With these images you can run your application with only the required Red Hat build of OpenJDK dependencies.
Determine module dependencies of your application using
jdeps
command:Copy to Clipboard Copied! Toggle word wrap Toggle overflow ./jdk-17/bin/jdeps -s ./sample/HelloWorld.class
$ ./jdk-17/bin/jdeps -s ./sample/HelloWorld.class HelloWorld.class -> java.base HelloWorld.class -> java.logging
Build a custom java runtime image for your application:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow ./jdk-17/bin/jlink --add-modules java.base,java.logging --output custom-runtime du -sh custom-runtime ./custom-runtime/bin/java --list-modules
$ ./jdk-17/bin/jlink --add-modules java.base,java.logging --output custom-runtime $ du -sh custom-runtime 50M custom-runtime/ $ ./custom-runtime/bin/java --list-modules java.base@17.0.10 java.logging@17.0.10
NoteRed Hat build of OpenJDK reduces the size of your custom Java runtime image from a 313 M runtime image to a 50 M runtime image.
You can verify the reduced runtime of your application:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow ./custom-runtime/bin/java sample.HelloWorld
$ ./custom-runtime/bin/java sample.HelloWorld Jan 14, 2021 12:13:26 PM HelloWorld main INFO: Hello World!
The generated JRE with your sample application does not have any other dependencies.
You can distribute your application together with your custom runtime for deployment.
NoteYou must rebuild the custom Java runtime images for your application with every security update of your base Red Hat build of OpenJDK.