アプリケーション配布用に小さなJREを作る
  Java, プログラミング

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

Jigsawによるモジュール化は自作アプリケーションやサードパーティー製ライブラリの依存関係の解決に役立つだけではありません。Javaの標準クラスライブラリも複数のモジュールに分割され、必要なモジュールのみで構成された小さなJava Runtime Environment(実行環境)を作成できるようになりました。

この小さなJREを作る機能はモジュール対応していない(Java 8以前の)アプリケーションでも利用することができます。

JREが小さくなればアプリケーションにバンドルするのも容易になりますね。Project Jigsawを使って小さなJREを作成する手順をまとめました。

JDKを用意する

まずはJDKを用意しましょう。

JDK 9、JDK 10はOracleの下記サイトからダウンロードすることができます。

OpenJDK
2018年9月にリリースされるJava 11以降、
OracleはJDKとJREを無償公開しなくなります。
代わりにOracle版と同等の機能を持つJDKとJREが
OpenJDK からダウンロードできるようになる予定です。

インストーラーを使ってインストールするか、もしくはJDKアーカイブを単に展開した場合は、jdk-9.0.4\bin などをPATHに追加してJavaコマンド群を使えるようにしておいてください。

サンプルプログラムを作る

はじめに簡単なサンプルプログラムを作っておきましょう。お馴染みのHello, World!!をコンソールに表示するだけのプログラムです。以下のソースコードをHelloWorld.javaというファイル名で保存します。

HelloWorld.javaクリップボードへコピー
public 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オプションを付けて実行します。

hello.jar
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.jmodjava.sql.jmodjava.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\binPATHを通します。

コマンドプロンプト
C:\>PATH=C:\jre-min\bin;%PATH%

サンプルプログラムを実行します。

コマンドプロンプト
C:\>java -jar hello.jar Hello, World!!

無事に動きましたね! hello.jarjre-min をバンドルして配布すれば、Javaをインストールしていない環境でもアプリケーションが実行できます。

もっと簡単なバッチファイルを!

jdepsで依存モジュールを確認してからjlinkで小さなJREを作る、同じ手順を繰り返していると次第に面倒になってきますよね。このjdepsjlinkを使った手順を自動化するバッチファイルcreate-jre.batを作ってみました。

上記ZIPファイルをダウンロード、展開して中に入っているcreate-jre.batsed.exePATHの通った場所に配置します。Javaコマンド群にもPATHを通す必要がありますので、create-jre.batsed.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待ちという開発者にも是非試してみていただきたい機能です。