JEP 493 Linking Run-Time Images without JMODs まとめ
- JDKベンダがJDKをビルドする際に指定可能なオプション
--enable-linkable-runtime
が追加された(JDK利用者側は特に気にすることはない) --enable-linkable-runtime
オプションが有効な場合、JDK に含まれるJMODファイルが省略される- JMODファイルは
jlink
ツールで利用されていたが、--enable-linkable-runtime
オプションが有効な場合は、jlink
ツールが自身でランタイムイメージから必要なリソースを抽出するようになったため、JMODファイルが省略可能 --enable-linkable-runtime
はあくまでJDK自身のビルドオプションであり、オプションを有効にするかどうかはJDKベンダ次第- JMODファイルが省略されることで、JDK自体のサイズが約25%削減できる
- コンテナ・イメージは、コンテナ・レジストリから頻繁にコピーされるため、JDKのインストール・サイズを縮小することが効率的
以下 JEP 内容
Summary
jlink
ツールを拡張し、JMODファイルを使わずにカスタムランタイムイメージを作成できるようにします。
これによりJDKのサイズが約25%削減できます。
この機能はJDKのビルド時に有効にする必要があり、デフォルトでは有効になりませんし、JDKベンダーによっては有効にしないことを選択する場合もあります。
Goals
モジュールが、スタンドアロンの JMODファイル、モジュールJARファイル、または以前にリンクされたランタイムイメージの一部であるかによらず、ランタイムイメージをリンクできるようにします。
Motivation
クラウド環境では、インストールされたJDKを含むコンテナ・イメージが、コンテナ・レジストリからネットワーク経由で自動的かつ頻繁にコピーされるため、ファイルシステム上のJDKのインストール・サイズは重要になります。JDKのサイズを小さくすれば、こうした作業が効率化されます。
JDKには、2つの主要なコンポーネントがあります。 1つは実行可能なJavaランタイム・システムである「ランタイム・イメージ」、もう1つはランタイム・イメージの各モジュールに対応するJMODフォーマットの「パッケージ・モジュール」です。
JMODファイルは jlink
ツールが カスタムランタイムイメージ を作成するときに使用します。
JDK に含まれるランタイムイメージは、それ自身がランタイムイメージであり、jlink
を介して JMOD ファイルから作成されます。
したがって、ランタイムイメージ内のすべてのクラスファイル、ネイティブライブラリ、設定ファイル、その他のリソースは、JMODファイルの中に重複して存在しています。
実際、完全なJDKのJMODファイルはJDKの総サイズの約25%を占めています。
もし jlink
ツールを拡張して、ランタイムイメージ自体からクラスファイル、ネイティブライブラリ、設定ファイル、その他のリソースを抽出することができれば、JMODファイルを省くことでインストールされるJDKのサイズを劇的に小さくすることができます。
Description
新しい JDK build-time 設定オプション --enable-linkable-runtime
は、 jlink
ツールが JDK の JMOD ファイルを使用せずにランタイムイメージを作成できるように JDK をビルドします。
この場合、 jmods
ディレクトリは存在しなくなり、デフォルトの設定でビルドされたJDKより約25%小さくなります。
$ configure [ ... other options ... ] --enable-linkable-runtime $ make images
jlink
ツールは、JMOD ファイルとモジュール化された JAR ファイルの両方を利用することができることは変わりません。--enable-linkable-runtime
が有効になっている JDK ビルドでは、 jlink
はその一部であるランタイムイメージからモジュールを使うことができます。
jlink
の --help
出力には、このオプション有無が表示されます。
$ jlink --help Usage: jlink <options> --module-path <modulepath> --add-modules <module>[,<module>...] ... Capabilities: +run-time-image $
run-time-image
トークンは、使用する jlink
ツールがランタイムイメージから JDK モジュールをリンクできることを意味します。
この機能がない場合、トークンは -run-time-image
です。
新しい機能を持つ jlink
のバージョンは、利用可能であれば、常にモジュールパス上の JMOD ファイルから JDK モジュールを利用することを優先します。
モジュールパス上に java.base
というモジュールが見つからない場合のみ、そのモジュールが属するランタイムイメージからモジュールを消費します。
その他のモジュールは --module-path
オプションで jlink
に指定する必要があります。
新しい機能を使って jlink
を実行したときのユーザーエクスペリエンスは、機能なしで jlink
を実行したときとまったく同じになります。
いくつかのモジュールを省いてランタイムイメージのサイズを小さくしたい場合、必要なモジュールだけを含めれば、JMODファイルは必要なくなります。
例えば、java.xml
と java.base
モジュールだけを含むランタイムイメージを作成する場合、jlink
の呼び出しに変化はありません。
$ jlink --add-modules java.xml --output image $ image/bin/java --list-modules java.base@24 java.xml@24 $
jlink
の出力は、モジュールがJMODファイルからリンクされた場合とまったく同じです。結果として得られるランタイムイメージは、完全なJDKランタイムイメージよりも約60%小さくなります。
より複雑な呼び出しでも同じです。例えば、ライブラリ lib
を必要とするアプリケーションモジュール app
を含むランタイムイメージを作成したいとします。
これらのモジュールは モジュール型 JAR ファイル として mlib
ディレクトリにパッケージされていた場合、今まで通りに --module-path
オプションを使って jlink
にモジュールを指定します。
$ ls mlib app.jar lib.jar $ jlink --module-path mlib --add-modules app --output app $ app/bin/java --list-modules app lib java.base@24 $
jlink
ツールは、モジュール化された JAR ファイル app.jar
と lib.jar
から app
と lib
モジュールのクラスファイルとリソースをコピーします。
jlink
ツールは JDK のランタイムイメージから JDK モジュールのクラスファイル、ネイティブライブラリ、設定ファイル、その他のリソースを抽出します。
jlink
の--verbose
オプションは各モジュールのオリジンを表示するようになります。
$ ls custom-jmods foo.jmod $ jlink --add-modules foo \ --module-path=custom-jmods \ --verbose \ --output foo-image Linking based on the current run-time image java.base jrt:/java.base (run-time image) foo file:///path/to/custom-jmods/foo.jmod Providers: java.base provides java.nio.file.spi.FileSystemProvider used by java.base $
この例では、モジュール java.base
は現在のランタイムイメージから抽出され、モジュール foo
は JMOD ファイル foo.jmod
からリンクされていることを示します。
Not enabled by default
デフォルトのビルド構成は現状のまま変更はありません。
出来上がったJDKにはJMODファイルが含まれ、jlink
ツールはJMODファイルなしでは動作しません。
JDKビルドにこの機能が含まれているかどうかは、JDKベンダ次第になります。
将来のリリースでは、この機能をフォルトで有効にすることを提案する可能性があります。
Restrictions
enable-linkable-runtime
でビルドされたJDKのjlink
ツールは、デフォルトの設定でビルドされたJDKのものと比べて、いくつかの制限があります。
jlink
ツールを含むランタイムイメージを作成するためにjlink
を使用することはできません。jlink
ツールはjdk.jlink
モジュールに含まれているので、以下は失敗します(将来、この制限が問題になるようであれば、再検討する可能性があります)$ jlink --add-modules jdk.jlink --output image Error: This JDK does not contain packaged modules and cannot be used \ to create another run-time image that includes the jdk.jlink module
ユーザが変更可能な設定ファイルが編集されると
jlink
は失敗します
JDKの conf
ディレクトリには、開発者がJDKを設定するために編集する様々なファイルが含まれています。
特に conf/security/java.security
ファイルは、セキュリティプロバイダや暗号アルゴリズムなどを設定します。
デフォルトのビルドでは、 jlink
は JDK の JMOD ファイルから JDK のモジュールのユーザが編集可能な設定ファイルをコピーします。
JMOD ファイルがない場合、jlink
はランタイムイメージから設定ファイルをコピーし、元のファイルと異なるファイルがあると失敗します
```shell
$ jlink --add-modules java.xml --output image
Error: [...]/bin/conf/security/java.security has been modified
```
この制限は jlink
がアドホックまたは安全でない設定でランタイムイメージを作成するのを防ぎます。セキュリティ設定が、例えば、デフォルトでは無効になっている旧式のメッセージダイジェストアルゴリズムを有効にするように変更された場合、その設定を新しいランタイムイメージにコピーすることは不適切です。
- Linux/x64上で
jlink
を実行してWindows/x64用のランタイム・イメージを作成するといったクロスリンクはできない patch-module
を使用しているランタイムイメージからのリンクはサポートされない--module-path
オプションに別のランタイムイメージを指定するなど、別のランタイムイメージからモジュールを抽出してリンクすることはサポートされない
Alternatives
JDKベンダは、JDKのJMODファイルを別のダウンロードとして提供することができます。 いくつかのLinuxディストリビューションは既に、JDKのランタイムイメージと、それに対応するJMODファイルのインストールパッケージを提供しています。
2つ目のパッケージがインストールされていないと jlink
ツールは動作しないので、このアプローチは脆く、JDKランタイムイメージとJMODファイルが異なるコンテナイメージ層で競合する可能性があるクラウド環境には適していません。