Javaのモジュールシステムについて、学習内容をまとめたものを書いていきます。
モジュールシステム
モジュールシステム(module system)
複数のパッケージを「モジュール」という単位でまとめられる仕組み。
目的
- パッケージ単位の情報隠蔽を実現する
- アプリケーションモジュールと JDK モジュールのリンクを容易に構築する
モジュールの作成手順
- モジュール用のディレクトリを作成する
- そのディレクトリに
module-info.javaを作成する - 例えば次のようにコンパイルする
$ javac -d mods/moduleA \
src/moduleA/com/example/module-info.java \
src/moduleA/com/example/Main.java
-
mods/moduleA:クラスファイルの出力先ディレクトリ -
src/moduleA/module-info.java:コンパイル対象ファイル① -
src/moduleA/com/example/Main.java:コンパイル対象ファイル②
module-info.java の記述内容
module-info.java には次の2点を記述します。
- どの パッケージ を公開するか(
exports) - どの モジュール を利用するか(
requires)
module moduleA {
exports package1; // 公開するパッケージ
exports package2;
requires module1; // 利用するモジュール
requires module2;
}
モジュールの実行手順
$ java --module-path mods -m moduleA/com.example.Main
-
mods:モジュールが存在するディレクトリ -
moduleA:モジュール名 -
com.example.Main:実行する完全修飾クラス名
モジュール間の依存関係
モジュールグラフ
モジュールグラフ(module graph)
モジュール間の依存関係を表した図。
モジュールAがモジュールBに依存する場合、A → B の矢印で表現される。
推移的な依存関係
推移的な依存関係(transitive dependencies)
自分が依存しているモジュールを、自分を利用する側にも引き継がせる仕組み。
例えば次の状態では、moduleA は moduleC を直接利用できません。
module moduleA {
requires moduleB;
}
module moduleB {
requires moduleC;
}
moduleA から moduleC を利用できるようにするには、moduleB を次のように修正します。
module moduleB {
requires moduleC transitive;
}
相互依存によるコンパイルエラー
相互依存
複数のモジュールが互いに依存している状態。
コンパイラが依存関係を解決できず、コンパイルエラーになる。
モジュールに関するコマンド
モジュールの情報を確認する
方法は2つあります。
-
javaコマンドの--describe-module$ java --module-path mods --describe-module moduleA -
jmodコマンドのdescribe$ jmod create --class-path mods/moduleA moduleA.jmod $ jmod describe moduleA.jmod
JMODファイル形式
クラスファイルなどを1つのモジュールとしてまとめた形式。
ネイティブコードを含められる点が JAR との大きな違い。
モジュールの依存関係を確認する
-
java --show-module-resolution$ java --module-path mods --show-module-resolution -m moduleA/com.example.a.Main -
jdepsコマンド$ jdeps mods/moduleA
非公開パッケージを一時的に利用する
-
javac --add-exportsオプション
exportsされていないパッケージを一時的に利用してコンパイルする。- 記法:
--add-exports (対象モジュール)/(公開パッケージ)=(利用モジュール) - あくまで緊急避難用。乱用は非推奨。
$ javac -d mods/moduleA \ --module-path mods \ --add-exports moduleB/com.example.b=moduleA \ src/moduleA/module-info.java \ src/moduleA/com/example/a/Main.java - 記法:
java.base モジュール
java.base モジュール
java.lang、java.util、java.io など、ほぼすべてのプログラムで使用される基本モジュール。
明示的に requires しなくても自動的に読み込まれる。
明示しない場合、モジュール情報の出力には次のように表示される。
module moduleA {
// ...
requires java.base mandated;
// ...
}
参考文献
-
志賀澄人. 徹底攻略 Java SE 11 Silver問題集 : [1Z0-815]対応. 東京, インプレス, 2019, p.371–392, 397, 412, 452, 453, 468, ISBN4-295-00762-5.
-
Deitel, Paul. “Java 9 Modulesの理解”. Oracle. https://www.oracle.com/jp/corporate/features/understanding-java-9-modules.html, (参照 2023-11-24).
-
tyab. “Java JMODファイルとは, JARファイルとの違い. ”. tyablog.net. 2020-04-05. https://tyablog.net/2020/04/05/java-how-different-jmod-and-jar/, (参照 2023-11-24).