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 it was necessary that the Java Runtime Environment was 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.
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:
java --list-modules
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.lang
, java.io
, java.math
, java.time
, java.util
, 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 javafx.*
, java.sql.*
, 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.
The jlink
tool
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 java.base
module:
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 (javabasert
).
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:
javabasert\bin\java --list-modules
we can print the list of modules that the new runtime supports, obtaining the following output:
java.base@16
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 HelloWorld
class:
public class HelloWorld { public static void main(String args[]) { System.out.print("Hello World!"); } }
simply use a command like the following:
javabasert\bin\java HelloWorld
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 javabasedeskrt
.
To check the correct definition of the environment, run the command:
javabasedeskrt\bin\java --list-modules
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.base
and java.deskto
p to our runtime, the latter module has dependencies on java.prefs
, java.xml
, 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.
The jdeps
tool
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:
jdeps HelloWorld.class
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.io
and java.lang
packages. Obviously, if the class belonged to the mypackage
package, then we would see mypackage
instead of the <unnamed>
string.
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 jlink and jdeps tools, we can use the –help option.
Conclusion
Undoubtedly the 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.
Author Notes
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.
> Platform Dependence
>
> 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.
That’s not true, it works just fine.
You just need both JDKs.
The one for the system where you want to run jlink to run jlink
and the one for the target platform to specify the JMOD files from.
Hi Björn, thank you for the clarification. I preferred to delete that part, then I will calmly update the article.
Thanks again
Claudio