The jlink tool assembles and optimizes a set of modules and their dependencies into a custom run-time image.1 It became part of the Java Platform with the advent of JPMS (which originated from Project Jigsaw2) in Java 9, along with a number of other tools related to the new modular system.

Java Platform Module System (JPMS)

Jigsaw image

The biggest change in Java 9 was arguably the inclusion of Project Jigsaw: Modules. Unlike modules seen before, this new modular system forces public APIs to explicitly created, and also allows for dependency checks at run-time; something that ended up in run-time exceptions previously. There is so much more to JPMS that I will explain here, so please do “Google” around for more information.

The entire JDK was rewritten into individual modules to help kick-start the support of modules. As a result you only need to specify the Java modules you use, ignoring the bulky additional modules. As you will see below, this where jlink begins to show it’s qualities.

Java Run-time Environments (JRE)

As of Java 9, Oracle stopped supplying a JRE as a separate product to the Java Development Kit (JDK). This shouldn’t be an issue for legacy installations, where many relatively-small Java Archives (JARs) would all share the same JRE (which is fairly large), because the JDK does still includes a JRE.

However, the power of JPMS is that developers have a few deployment choices: they could continue to deploy JARs for use with a separate JRE (potentially large if using the full JRE). Or, on the other hand, they could make use of jlink to produce custom JREs that only contain the necessary modules to run the supplied Java program.

I should note, that other deployment methods are available (e.g. JMODs and backwards compatible JARs etc…). However, the focus of this article article is to introduce JPMS and jlink.

jlink takes a Java 9+ JAR file and it’s dependencies to build a custom JRE containing only the modules required to run that JAR. So, if only “java.base” is required, for instance, then the final size of the JRE may end up very small. Well… small in Java terms… perhaps we can talk about the Ahead Of Time Compiler another time.

This is great for deploying applications for IAT purposes, or for controlling which Java features are available to the application.

A Simple jlink Example

Source code can be found here: https://bitbucket.org/jennettwheeler/jpms-hello-world

Project Structure

We will begin by creating a new project in our preferred IDE. I prefer IntelliJ IDEA, but you should be able to use any for this basic example.

You should have installed Java 9 or greater and ensured that your IDE is using it.

As with all Java applications, we need a sources directory and a build directory.

Java file structure of Hello World JPMS Module

Hello World

Next, we write our HelloWorld.java class.

package uk.co.jennettwheeler.hello_world;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

And finally, we need to setup the module. To do this we need a file called “module-info.java” at the root of the sources directory.

module uk.co.jennettwheeler.hello_world {
    requires java.base;
}

It is good practice to prefix your modules in reverse domain name notation (I did the same with my Java package above).

Building and running this code should print “Hello World” to the console:

If it does, congratulations! You now have a Java application which uses the JPMS.

Introducing jlink

Switching to a terminal (I am using the built in terminal in IntelliJ IDEA), we can run the app again to check it still works in the terminal:

C:\Users\James\IdeaProjects\jpms-hello-world>java --module-path out/production -m uk.co.jennettwheeler.hello_world/uk.co.jennettwheeler.hello_world.HelloWorld
> Hello World

Now lets run jlink!

jlink --module-path out/production --add-modules uk.co.jennettwheeler.hello_world --output out/hellojre

This produces a folder named “hellojre” in the output directory and that’s pretty much it!

In the /bin directory you’ll find the java executable, and you can use this to run your program.

out\hellojre\bin\java -m uk.co.jennettwheeler.hello_world/uk.co.jennettwheeler.hello_world.HelloWorld

You’ll notice the similarities to how ran the code above, except we no longer need to point to HelloWorld module because they’re included in the JRE.

By default, the generated JRE will only work for the platform on which it was created. However,  in the next article, we’ll discuss how to build for alternate platforms on whichever platform you’re using.

Next Steps

If you check out the jlink documentation1, you’ll find additional option to reduce the size further with compression, automatically create a program launch file, and more.

References

1.
jlink. Oracle JDK 9 Documentation. https://docs.oracle.com/javase/9/tools/jlink.htm. Accessed October 19, 2018.
2.
Project Jigsaw. OpenJDK. https://openjdk.java.net/projects/jigsaw/. Published September 22, 2017. Accessed October 19, 2018.

Series Part 2 →
JPMS: An introduction to the JPMS & jlink
Tagged on: