
- JEP 493 Linking Run-Time Images without JMODs まとめ
- Eclipse Temurin の JMOD
- Summary
- Goals
- Motivation
- Description
- Alternatives
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のインストール・サイズを縮小することが効率的
Eclipse Temurin の JMOD
Eclipse Temurin は JEP493 が有効になっており、JMODファイルが含まれていません。
Eclipse Temurin JDK 24.0.0+36 enables JEP 493 | Adoptium
badass-jlink-plugin を利用している場合、現在のところ JEP 493 / Temurin JDK 24 breaks plugin により jlink が動作しません。その場合は、JEP493 が無効な他の toolchain を指定することで回避できます。
java {
toolchain {
languageVersion = JavaLanguageVersion.of(24)
vendor = JvmVendorSpec.AMAZON
}
}
以下 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ファイルが異なるコンテナイメージ層で競合する可能性があるクラウド環境には適していません。