Java 9 の新機能 Project Jigsaw (プロジェクト ・ ジグソー) で Java に待望のモジュール機能が追加されました。

Jigsaw によるモジュール化は自作アプリケーションやサードパーティー製ライブラリの依存関係の解決に役立つだけではありません。Java の標準クラスライブラリも複数のモジュールに分割され、 必要なモジュールのみで構成された小さな Java Runtime Environment (実行環境) を作成できるようになりました。
この小さな JRE を作る機能はモジュール対応していない (Java 8 以前の) アプリケーションでも利用することができます。
JRE が小さくなればアプリケーションにバンドルするのも容易になりますね。Project Jigsaw を使って小さな JRE を作成する手順をまとめました。
JDKを用意する
まずは JDK を用意しましょう。
JDK 9、 JDK 10 は Oracle の下記サイトからダウンロードすることができます。
インストーラーを使ってインストールするか、 もしくは JDK アーカイブを単に展開した場合は、 jdk-9.0.4\bin などを PATH に追加して Java コマンド群を使えるようにしておいてください。
サンプルプログラムを作る
はじめに簡単なサンプルプログラムを作っておきましょう。お馴染みの Hello, World!! をコンソールに表示するだけのプログラムです。以下のソースコードを HelloWorld.java というファイル名で保存します。
HelloWorld.javapublic class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!!");
}
}
HelloWorld.java を保存したフォルダーに移動して、 javac コマンドでコンパイルします。
コマンドプロンプトC:¥>javac HelloWorld.java
これで、 HelloWorld.class ができました。次は jar コマンドを使って実行可能 JAR ファイルを作成します。
コマンドプロンプトC:¥>jar --create --file hello.jar --main-class HelloWorld HelloWorld.class
これで、 実行可能 JAR ファイル hello.jar ができました。さっそく、 実行してみます。
コマンドプロンプトC:¥>java -jar hello.jar Hello, World!!
上手くいきました。
次は、 この hello.jar を実行するのに必要な小さな JRE を作成していきます。
jdepsで依存モジュールを調べる
jdeps コマンドを使うとアプリケーション (JAR ファイル) が依存しているモジュールを調べることができます。
サンプルプログラム hello.jar の依存モジュールを調べる場合は以下のように --list-deps オプションを付けて実行します。
コマンドプロンプトC:¥>jdeps --list-deps hello.jar java.base
hello.jar が依存しているモジュールは java.base だけであることが分かります。(複数のモジュールに依存している場合は複数行表示されます。)
jlinkに依存モジュールを指定して小さなJREを作る
hello.jar が依存しているモジュールが java.base であることが分かったので、 次に java.base のみの JRE を作ります。これには jlink というコマンドを使います。
以下のように引数を指定して jlink を実行します。
コマンドプロンプトC:¥>jlink --compress=2 --module-path "C:¥jdk-9.0.4¥jmods" --add-modules java.base --output jre-min
| 引数 | 説明 |
|---|---|
| –compress=2 | JRE を圧縮するオプションです。 |
| –module-path | モジュールが格納されているパスを指定します。JDK を展開すると jmods というフォルダーがあるのでそのパスを指定します。このフォルダーの中に java.base.jmod や java.sql.jmod、 java.xml.jmod など様々なモジュールが格納されています。 |
| –add-modules | jdeps で調べたモジュール名を指定します。今回は java.base だけですが、 モジュールが複数ある場合はカンマで区切って並べます。 |
| –output | JRE を出力するパスを指定します。 |
他のオプションは jlink --help で確認することができます。
これで jre-min というフォルダーが作成されます。これが hello.jar を実行するために作成した小さな JRE です。

サイズは 24MB になっています。この jre-min フォルダーを ZIP 圧縮するとさらに 15MB まで小さくなりました。これならアプリケーションに Java 実行環境をバンドルするのも難しくないですね。
小さなJREでアプリケーションを実行してみる
本当に、 これで Java アプリケーションが実行できるのでしょうか? 新しいコマンドプロンプトを起動して確認してみましょう。できれば、 Java コマンド群に PATH が通っていないほうが分かりやすいです。
はじめに、 このコマンドプロンプトから Java 実行環境が見えていないことを確認します。誤って作業に使用した JDK でアプリケーションが実行されないようにするためです。
コマンドプロンプトC:¥>java 'java' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。
このコマンドプロンプトでは java コマンドが見つからないので、 他の Java 実行環境が使われることはありません。次に、 作成した jre-min\bin に PATH を通します。
コマンドプロンプトC:¥>PATH=C:¥jre-min¥bin;%PATH%
サンプルプログラムを実行します。
コマンドプロンプトC:¥>java -jar hello.jar Hello, World!!
無事に動きましたね! hello.jar に jre-min をバンドルして配布すれば、 Java をインストールしていない環境でもアプリケーションが実行できます。
もっと簡単なバッチファイルを!
jdeps で依存モジュールを確認してから jlink で小さな JRE を作る、 同じ手順を繰り返していると次第に面倒になってきますよね。この jdeps と jlink を使った手順を自動化するバッチファイル create-jre.bat を作ってみました。
上記 ZIP ファイルをダウンロード、 展開して中に入っている create-jre.bat と sed.exe を PATH の通った場所に配置します。Java コマンド群にも PATH を通す必要がありますので、 create-jre.bat と sed.exe を JDK の bin フォルダーにコピーしてしまうのが簡単だと思います。
あとは Java コマンド群に PATH が通ったコマンドプロンプトで以下のコマンドを実行するだけです。
コマンドプロンプトC:¥>create-jre hello.jar
これで、 hello.jar を実行するのに必要な小さな JRE ができます。(使用した JDK のバージョンを含む jre-9.0.4.min のような JRE フォルダーが出力されます。)
小さな JRE (Minimized JRE) を作成する手順は以上です。
この JRE 縮小手順は、 モジュール化していない Java 8 以前のアプリケーションにも適用できますので、 Java 9、 Java 10 を見送って長期サポートの Java 11 待ちという開発者にも是非試してみていただきたい機能です。