Going Beyond Java 8: Create Custom Java Runtimes with jlink
Although Java 8 is currently the most popular version of Java by developers everywhere, tools like jlink allow us to go beyond Java 8 and create custom runtimes.
Join the DZone community and get the full member experience.Join For Free
According to some surveys such as that of JetBrains, version 8 of Java is currently the most used by developers all over the world, despite being a 2014 release. What you are reading is one in a series of articles titled “Going beyond Java 8”, inspired by the contents of my book “Java for Aliens”. These articles will guide the reader step-by-step to explore the most important features introduced starting from version 9. The aim is to make the reader aware of how important it is to move forward from Java 8, explaining the enormous advantages that the latest versions of the language offer.
Before Java 9, to run a Java application on any platform the Java Runtime Environment needed to be installed on it. Today the classic JRE no longer exists, and it is not automatically installed when we install the JDK as in the past. There is no longer the Java Plugin too, that was installed in browsers to allow the execution of applications that used the historical Applet and Java Web Start technologies (no longer available). Today, to allow the execution of a Java application on a particular platform, we can create a custom Java runtime that contains only the libraries that the program needs to run, and distribute it as part of the application itself. To do this, just use the tool introduced with the JDK 9 called jlink, which takes advantage of the JDK modularization.
With the introduction of the module concept in version 9, a major refactoring of the JDK has been done. This means that now the packages of the standard Java library are organized within modules (that physically, are simple folders).
In particular, the JDK version 16 defines 68 modules, but this number will probably change (in version Java 9 there were 98). We can check this by running the command:
which will print the list of all the modules present in the JDK that we report in the following table:
Figure 1 – JDK 16 Modules.
For example, the
java.base module contains the fundamental (base) packages such as
java.util.stream and many others.
What We Can Do Now
Before the modularization of the JDK, our programs had to take advantage of the complete installation of the Java Runtime Environment on the target platform. They, therefore, had all the JRE libraries available (such as
Applet) even if they were not used. All these libraries were included in the rt.jar file.
With modules, on the other hand, it is possible to create customized runtimes. In fact, from Java 9 onwards, we can distribute our programs bringing with them only the necessary libraries. In this way, we can reduce the size of the application and improve its performance. Furthermore, it will not be necessary to install the JRE on the target machine, since we will create a customized and optimized Java runtime that we will distribute together with the application itself.
Java 9 introduced a new tool called jlink, a very simple command-line tool to use. It allows us to create custom runtimes only with the modules that our application needs. For example, with the following command, we will create a runtime containing only the
jlink --add-modules java.base --output javabasert
In fact, with the
--add-modules option we add the
java.base module to the runtime, while with the
--output option we give the name to the runtime (
At this point
jlink will create a runtime inside a folder called
javabasert, with the entire structure consisting of folders bin, lib, include, conf, legal.
Figure 2 - The javabasert custom runtime structure, created with jlink
The size of the
javabasert runtime we created does not exceed 40 megabytes, while the full JDK is approximately 290 megabytes in size. We can also fully compress our runtime using the
--compress 2 option to get a size of about 27 megabytes.
With the following command:
we can print the list of modules that the new runtime supports, obtaining the following output:
which confirms that with
javabasert we can only exploit the libraries included in the
java.base module of version 16.
If we wanted to run an application using the newly created runtime, considering the usual
simply use a command like the following:
Transitive Dependencies Between Modules
If we want to create a runtime that also includes the
java.desktop module which contains the libraries to create graphical interfaces, we can run the command:
jlink --add-modules java.base,java.desktop --output javabasedeskrt
where we called the new custom runtime
To check the correct definition of the environment, run the command:
which will produce the following output:
java.base@16 java.datatransfer@16 java.desktop@16 java.prefs@16 java.xml@16
In practice, even if we thought we had only added two modules, in reality we also find others. This is because the modules are linked by dependency relationships. In particular, even if we asked
jlink to add only the
java.desktop to our runtime, the latter module has dependencies on
java.datatransfer and also with
java.base. In fact, we could also have avoided specifying
java.base between the modules to be included, we would have obtained the same result.
To understand how to create the right runtime, in JDK 9 the jdeps tool was revised to support modular dependencies. Also, this tool is very simple to use. For example, considering the
HelloWorld class, the following command:
will produce the following output:
HelloWorld.class -> java.base <unnamed> -> java.io java.base <unnamed> -> java.lang java.base
which shows us the dependence of the
HelloWorld class on the
java.base module, and since our class does not belong to a package, it is clear that the anonymous package (unnamed) depends on the
java.lang packages. Obviously, if the class belonged to the
mypackage package, then we would see
mypackage instead of the
jdeps command can also take folders and JAR files as well as classes as input.
To view all the options available for use with both the
jdeps tools, we can use the
jlink tool is platform-dependent. This means that if we want to deploy a Java application on various platforms, then we have to create custom runtimes on each of the platforms via
jlink. It is not possible to create a custom runtime on a particular platform for a different platform. For example, we cannot create a Linux runtime using
jlink on a Windows System.
jlink tool represents a step towards the future for Java. In fact, by providing very little information we can create customized runtimes for our applications, making them more performing, less bulky, and easier to distribute. The support of the
jdeps tool allows us to understand which modules are needed in the runtime to be created for our applications. Furthermore, both tools are particularly easy to use.
Even ignoring the increased security offered by the latest versions of the JDK, there are plenty of reasons to upgrade your knowledge of Java, or at least your own Java runtime installations. My book "Java for Aliens", which inspired the " Going beyond Java 8" series, contains all the information you need to learn Java from scratch, and uses a well-tested teaching method that has been perfected over 20 years of experience, which makes learning simple and exciting. It is also structured to deepen the topics and have superior knowledge that can make a difference in your career.
This article is mainly inspired by section 19.3 of chapter 196 of the book “Java for Aliens”
For more information visit https://www.javaforaliens.com.
Published at DZone with permission of Claudio De Sio Cesari. See the original article here.
Opinions expressed by DZone contributors are their own.