JDK9: Howto Create A Java Run-Time Image With Maven?

At the moment JDK 9 is only available as Early Access (EA) to let the community take a look how it works and what can be improved. Apart from all the news for example about the modular system Jigsaw etc. There is one important question:

How can I create a Java Run-Time Image with Maven? But before we begin: What is a Java Run-Time Image?

The simplest answer I can give: You have a running Java Runtime environment where all parts have been removed which are not really used by the current application. Based on the modularization of the Java Plattform itself you can think of many parts which can be removed by a usuall application. This in the end will give you the opportunity to deliver only the Java Run-Time Image including your application. So this means in the target environment you do not need to install a full blown JRE. This safes space in particular if you think about Microservices.

There are a few things which need to be payed attention to related to this post:

Everything what is written here is:

  • Currently in a prove of concept state.
  • Everything here is speculative.

So this means it can become official Maven plugins or not. The intention is to get some feedback from interessted volunteers to see others working with JDK9 and about their experiences and to see if Maven needs to go different ways or if the current way is ok.

So let use start with the interesting part. We start with a simple multi module project and see how this works. The example project currently contains three modules mod-1, mod-2 and mod-jar. The mod-jar is a usual jar project which produces a jar file as result.

The only important part is that this contains a module-info.java file which is compiled into the jar file. This jar file is a modular JAR file, cause it contains a module-info.class file at the root location of the jar.

The mod-1 and mod-2 are currently explictly producing jmod files which contain the module name in its file name. At the moment those modules are placed into the target/jmods/ directory of the appropriate project.

So now we have summarized the different projects which produce either a jar or jmod file but to get a Java Run-Time Image we have to use the jlink command of JDK 9 which is the Java Linker which produces the Run-Time Image. Then handling of jlink is currently put into the mod-jlink module which contains a packaging of jlink.

The example project uses two new created Maven plugins ([maven-jmod-plugn] and maven-jlink-plugin) which currently implement the handling for jmod and the jlink packaging type. They exist only as SNAPSHOTs which are available via the Apache Software Foundation repository. If you like to use them you have to configure them into your settings.xml or in your repository manager. One more thing is needed to be set up: toolchains to configure the environment like where to find the JDK9 etc.

If you run the whole project via:

 1mvn clean package
 2...
 3[INFO] ------------------------------------------------------------------------
 4[INFO] Building com.soebes.nine.one 1.0-SNAPSHOT
 5[INFO] ------------------------------------------------------------------------
 6[INFO]
 7[INFO] --- maven-clean-plugin:3.0.0:clean (default-clean) @ com.soebes.nine.one ---
 8[INFO] Deleting /Users/kama/jdk-9-test/maven-example/mod-1/target
 9[INFO]
10[INFO] --- maven-toolchains-plugin:1.1:toolchain (default) @ com.soebes.nine.one ---
11[INFO] Required toolchain: jdk [ vendor='oracle' version='1.9' ]
12[INFO] Found matching toolchain for type jdk: JDK[/Library/Java/JavaVirtualMachines/jdk1.9.0_ea+172.jdk/Contents/Home]
13[INFO]....
14...
15[INFO]
16[INFO] --- maven-compiler-plugin:3.6.0:compile (default-compile) @ com.soebes.nine.one ---
17[INFO] Toolchain in maven-compiler-plugin: JDK[/Library/Java/JavaVirtualMachines/jdk1.9.0_ea+172.jdk/Contents/Home]
18[INFO] Changes detected - recompiling the module!
19[INFO] Compiling 2 source files to /Users/kama/jdk-9-test/maven-example/mod-1/target/classes
20[INFO]
21...
22...
23[INFO]
24[INFO] --- maven-jlink-plugin:3.0.0-SNAPSHOT:jlink (default-jlink) @ mod-jlink ---
25[INFO] Toolchain in maven-jlink-plugin: jlink [ /Library/Java/JavaVirtualMachines/jdk1.9.0_ea+172.jdk/Contents/Home/bin/jlink ]
26[INFO] The following dependencies will be linked into the runtime image:
27[INFO]  -> com.soebes.examples.jdk9:com.soebes.nine.one:jmod:1.0-SNAPSHOT
28[INFO]  -> com.soebes.examples.jdk9:com.soebes.nine.two:jmod:1.0-SNAPSHOT
29[INFO]  -> com.soebes.examples.jdk9:com.soebes.nine.jar:jar:1.0-SNAPSHOT
30[INFO] Building zip: /Users/kama/jdk-9-test/maven-example/mod-jlink/target/mod-jlink-1.0-SNAPSHOT.zip
31[INFO]
32[INFO] --- maven-site-plugin:3.6:attach-descriptor (attach-descriptor) @ mod-jlink ---
33[INFO] Skipping because packaging 'jlink' is not pom.
34[INFO] ------------------------------------------------------------------------
35[INFO] Reactor Summary:
36[INFO]
37[INFO] parent ............................................. SUCCESS [  0.931 s]
38[INFO] com.soebes.nine.one ................................ SUCCESS [ 17.019 s]
39[INFO] com.soebes.nine.two ................................ SUCCESS [  1.007 s]
40[INFO] com.soebes.nine.jar ................................ SUCCESS [  0.926 s]
41[INFO] mod-jlink .......................................... SUCCESS [  2.602 s]
42[INFO] ------------------------------------------------------------------------
43[INFO] BUILD SUCCESS
44[INFO] ------------------------------------------------------------------------
45[INFO] Total time: 23.200 s
46[INFO] Finished at: 2017-06-06T20:08:54+02:00
47[INFO] Final Memory: 19M/385M
48[INFO] ------------------------------------------------------------------------

If everything works than you will find the Java Run-Time Image:

 1cd mod-jlink/target/jlink
 2~/jdk-9-test/maven-example/mod-jlink/target/jlink (master)$ ls -la
 3total 8
 4drwxr-xr-x   8 kama  staff  272 Jun  6 00:10 .
 5drwxr-xr-x   4 kama  staff  136 Jun  6 00:10 ..
 6drwxr-xr-x   4 kama  staff  136 Jun  6 00:10 bin
 7drwxr-xr-x   4 kama  staff  136 Jun  6 00:10 conf
 8drwxr-xr-x   7 kama  staff  238 Jun  6 00:10 include
 9drwxr-xr-x   3 kama  staff  102 Jun  6 00:10 legal
10drwxr-xr-x  19 kama  staff  646 Jun  6 00:10 lib
11-rw-r--r--   1 kama  staff   97 Jun  6 00:10 release

You can check this Java Run-Time first via:

1~/jdk-9-test/maven-example/mod-jlink/target/jlink (master)$ bin/java --list-modules
2com.soebes.nine.jar
3com.soebes.nine.one@1.0-SNAPSHOT
4com.soebes.nine.two@1.0-SNAPSHOT
5java.base@9-ea

which shows that this JRE only contians those modules which are need. Of course you can check the size of generated image on the hard drive:

1~/jdk-9-test/maven-example/mod-jlink/target/jlink (master)$ du -h -d 1 .
2144K    ./bin
3 76K    ./conf
4184K    ./include
5 44K    ./legal
6 35M    ./lib
7 35M    .

So this means the whole Java Run-Time Image is only 35 MiB in size. You can check against a full fledged JRE and compare that with the 35 MiB.

To test different modules in that Java Run-Time Image you can call them like this:

1~/jdk-9-test/maven-example/mod-jlink/target/jlink (master)$ bin/java com.soebes.example.nine.jar.Main
2Main from Java 9 (jar)
3~/jdk-9-test/maven-example/mod-jlink/target/jlink (master)$ bin/java com.soebes.example.nine.one.Main
4Main one from Java 9
5~/jdk-9-test/maven-example/mod-jlink/target/jlink (master)$ bin/java com.soebes.example.nine.two.Main
6Main two from Java 9

Conclusion

This is the first step of Maven into a support of JDK 9 tools like jlink and [jmod]. Other tooling like maven-jdeps-plugin already exist for a longer time.

This currently is a prove of concept and not an official statement. This is intended to get feedback of others working with JDK9 and see if we are doing right or not.

Apart from that you see the opportunities which JKD9 with it's Run-Time Images is offering. Based on the current implementation of the plugins it would not be very complicated to migrate and existing application (only command line apps ??) to a Java Run-Time Image.