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 待ちという開発者にも是非試してみていただきたい機能です。