[JAVA] Create a JVM for app distribution with JDK9 modules and jlink

The long-awaited Java 9 has finally been released ahead of JavaOne 2017!

By the way, speaking of Java 9, what is of concern is the module function by jigsaw. I often see how to use the module, but I was personally interested in jlink, so I summarized the results I tried.

Introduction

Regarding Jigsaw, at least for now, it's not possible to replace a single binary like fat-jar or go language alone.

However, it is possible to generate a JVM for distribution including the application by using the module and jlink, and this time I will explain about it. I will not mention that the module has made it possible to improve the disclosure range and detect dependencies early, so I will talk about this article % B5% E3% 83% BC% E3% 83% 93% E3% 82% B9% E3% 81% 8C% E5% BF% 85% E8% A6% 81% E3% 81% A8% E3% 81% 99 % E3% 82% 8B% E3% 83% A9% E3% 82% A4% E3% 83% 96% E3% 83% A9% E3% 83% AA) I think you should refer to it.

Code preparation

First, prepare the code. Make a sample that the library is called in three layers from the application like the following.

alt

What was made here. I will omit the details because I will not talk about it in particular, but I put module-info.java in each top directory and write the module settings. https://github.com/koduki/example-jlink

Build

Next is the build of each module.

Before that, first create a directory for module placement.

$ mkdir modules

Obviously, we will build in order from the one with no dependency.

$ javac -d commons/classes/ -cp commons/src/main/java $(find commons/src/main/java -name "*.java")
$ jar cvf modules/commons.jar -C commons/classes/ .

The build looks basically the same as a normal jar, except that you specify the module directory with the p option at compile time. Also, be aware that older versions have the option listed as mp.

$ javac -d libs/classes/ -cp "libs/src/main/java/" -p modules/ $(find libs/src/main/java -name "*.java") 
$ jar cvf modules/libs.jar -C libs/classes/ .

Once the library is built, the main application. However, this is just like the others.

$ javac -d apps/classes/ -cp apps/src/ -p modules $(find apps/src -name "*.java")
$ jar cvf modules/app.jar -C apps/classes/ .

It can be executed in the following form.

$ java -p modules/ -m apps/cn.orz.pascal.app.MyApp
Hello, cn.orz.pascal.common.CommonLib
Hello, cn.orz.pascal.lib.MyLib
Hello, MyApp

Did you confirm the execution? When specifying a module, describe it in the form of module name / class to be executed with the m option.

Creating a JVM for distribution with JLink

With this alone, I'm not very happy from the distribution point of view, so it's finally time for JLink. With JLink, you can create a JVM with the minimum configuration required for the specified module. This means that you don't have to have a Swing or AWT library in your web app.

In the case of Mac, if you just installed it, the path does not pass, so correspond as follows.

$ export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/   
$ alias jlink=${JAVA_HOME}/bin/jlink     

Next is the execution of the link by jlink. This time, I also created a launcher that executes ʻapps / cn.orz.pascal.app.MyApp` and compressed the whole with zip.

$ jlink --compress=2 --module-path $JAVA_HOME/jmods:modules --add-modules apps --output dist/my-app --launcher myapp=apps/cn.orz.pascal.app.MyApp 

When executed, my-app is created in the dist directory. When executed, it is as follows.

$ ./dist/my-app/bin/myapp 
Hello, cn.orz.pascal.common.CommonLib
Hello, cn.orz.pascal.lib.MyLib
Hello, MyApp

Since my-app contains the specified module and the JVM with the minimum configuration, just distribute this directory and it will work as it is even in an environment without a JVM. It's portable!

The capacity is as follows this time. It feels pretty good.

$ du -h dist|tail -n1
 24M	dist

Summary

I tried how to make a JVM for application distribution by jlink. Although it is not packaged, it seems to be a lot easier to distribute to an environment where the JVM is not installed. If it's for server use, wouldn't it be a problem if you package it in Docker?

It is not suitable for distribution in a single binary such as command system, which was realized by go language or java fat-jar, but I think that it can be fully realized if something like electron-packager is made in the future.

Well then, Happy Hacking!

Recommended Posts

Create a JVM for app distribution with JDK9 modules and jlink
[Rails6] Create a new app with Rails [Beginner]
[Rails 5] Create a new app with Rails [Beginner]
Create a simple search app with Spring Boot
Create a portfolio app using Java and Spring Boot
Create a widget template for iOS14 with Intent Configuration.
Create a Chat app with WebSocket (Tyrus) + libGDX + Kotlin
Create a blog with Jekyll and GitHub Pages @ Theme setting
Tutorial to create a blog with Rails for beginners Part 1
[Rails] I tried to create a mini app with FullCalendar
Create a Hello World web app with Spring framework + Jetty
Create a blog with Jekyll and GitHub Pages @ Initial Settings
Tutorial to create a blog with Rails for beginners Part 2
How to create and launch a Dockerfile for Payara Micro
Tutorial to create a blog with Rails for beginners Part 0
Create a playground with Xcode 12
I want to create a chat screen for the Swift chat app!
Create a memo app with Tomcat + JSP + Servlet + MySQL using Eclipse
Create an app catalog site using CLI for Microsoft 365 with Docker
[Swift] Create a project with Xcode (ver 12.1) and display "Hello, World!"
Create a high-performance enum with fields and methods like Java with JavaScript
Create a flyway jar with maven and docker build (migrate) with docker-maven-plugin
[Java] Let's create a mod for Minecraft 1.16.1 [Add and generate trees]
[Java] Let's create a mod for Minecraft 1.14.4 [9. Add and generate trees]
Create a development environment for Ruby 3.0.0 and Rails 6.1.0 on Ubuntu 20.04.1 LTS
Create a restaurant search app with IBM Watson + Gurunavi API (with source)
Create a Docker Image for redoc-cli and register it on Docker Hub
Introduction to Android App Development 1 Installing JDK and Android Studio for mac
[Java] Let's create a mod for Minecraft 1.14.4 [8. Add and generate ore]
Let's create a parameter polymorphic mechanism with Generic Dao and Hibernate
[OpenJDK11 & JavaFX13] Build a javaFX app with IntelliJ + gradle and create a package that can be distributed with a lightweight JRE
Create a Vue3 environment with Docker!
Create an app with Spring Boot 2
Creating a timer app with a muddy
Create a new app in Rails
Create an app with Spring Boot
Create command line app with maven
Try to create a server-client app
Create exceptions with a fluid interface
Create a Maven project with a command
Create a fluentd server for testing
Inexperienced create a weather app using OpenWeatherMap and deploy it to Netlify
Create a Spring Boot app development project with the cURL + tar command
Create a simple CRUD with SpringBoot + JPA + Thymeleaf ② ~ Screen and function creation ~
Create an iOS shortcut app and quickly open the key with NFC
[Ruby on Rails] Create a pie chart for each column with Chartkick
[Java] Create a jar file with both compressed and uncompressed with the jar command
[Docker] How to create a virtual environment for Rails and Nuxt.js apps
Create a program to post to Slack with GO and make it a container
How to create a server executable JAR and WAR with Spring gradle
Create a LINEnews-style tech news summary app with Rails x LineBot! [Part 1]
Create a java web application development environment with docker for mac part2
How to make an app with a plugin mechanism [C # and Java]