1. モジュールシステム(Project Jigsaw)とは?
Java 9から導入された「モジュールシステム」。
一言でいうと、**「パッケージをさらにグループ化し、外部への公開範囲を厳格に制御する仕組み」**です。
従来のJavaでは、publicであればどこからでもアクセスできてしまいましたが、モジュールシステムによって「パッケージ単位で鍵をかける」ことが可能になりました。
【例題①:基礎中の基礎】
まずは、基本中の基本である「ファイル名」から確認しましょう。
Q:モジュール定義ファイルの名前として正しいものはどれですか?
module.javamodule-info.javamodule_info.classpackage-info.java
正解:2
モジュール定義ファイルは、ソースルート直下に必ず
module-info.javaという名前で作成する必要があります。アンダースコアではなく「ハイフン」である点に注意!
2. module-info.javaの5つの基本指令(Directives)
試験で最も狙われるのが、この設定ファイルの書き方です。以下の5つは暗記必須です。
| 指令 (Directive) | 役割 |
| requires | 依存する他のモジュールを指定する(インポート) |
| exports | 指定したパッケージを外部に公開する |
| opens | 実行時に「リフレクション」を許可する |
| provides…with | サービス提供(インターフェースの実装)を宣言する |
| uses | サービスを利用することを宣言する |
【例題②:exportsとrequiresの違い】
Q:特定のパッケージを外部モジュールに対して公開し、利用可能にするキーワードはどれですか?
requiresexportsopensto
正解:2
exportsは自分のパッケージを外部に「公開」します。逆に、外部モジュールを利用(インポート)する場合はrequiresを使います。
3. 試験最頻出!「推移的依存(requires transitive)」
AモジュールがBを必要とし、BがCを必要としている場合、AからCを直接見れるようにするのが「推移的依存」です。
【例題③:依存の引き継ぎ】
Q:『推移的依存』を実現するために使用する正しい構文はどれですか?
requires transitive モジュール名;exports transitive パッケージ名;opens transitive パッケージ名;public requires モジュール名;
正解:1
requires transitiveを使うと、自モジュールを利用する他のモジュールに対しても、その依存関係を自動的に引き継がせることができます。
4. カプセル化を解除する「opens」
通常、非公開のメンバーにはリフレクションでもアクセスできませんが、それを許可するのが opens です。
【例題④:リフレクション対策】
Q:実行時にのみ、リフレクションによる非公開メンバーへのアクセスを許可する設定はどれですか?
exportsopensrequiresprovides
正解:2
opensは、カプセル化を「開く」役割を持ちます。試験では「JSONライブラリがリフレクションを使うためにopensが必要」といった文脈で出ることがあります。
【例題⑤:公開先の限定】
Q:exportsキーワードで公開先を特定のモジュールだけに限定したい場合、どの構文を使用しますか?
exports パッケージ名 limited モジュール名;exports パッケージ名 to モジュール名;exports パッケージ名 for モジュール名;
正解:2
exports ... to ...の形式で、特定の相手にだけ公開を許可します。これを「修飾されたエクスポート」と呼びます。
5. 自動モジュールと無名モジュール(移行期の仕組み)
「モジュール化されていない古いJARファイルをどう扱うか」は得点源です。
【例題⑥:自動モジュール】
Q:module-info.classを持たないJARを『モジュールパス』に配置した際、どのようなモジュールとして扱われますか?
- 名前付きモジュール
- 無名モジュール
- 自動モジュール
正解:3
モジュールパス(–module-path)に置くと 「自動モジュール」 になり、ファイル名からモジュール名が自動生成されます。
【例題⑦:無名モジュール】
Q:クラスパス上に配置されたすべてのクラスが属するモジュールを何と呼びますか?
- 無名モジュール
- 自動モジュール
- 基本モジュール
正解:1
従来の「クラスパス(–class-path)」に置かれたものは、すべて 「無名モジュール」 扱いになります。
6. 強力なコマンドラインツール(jdeps / jlink)
エンジニアなら知っておきたい、解析と配布のためのツールです。
【例題⑧:依存関係の解析】
Q:モジュールの依存関係を解析するために使用するコマンドはどれですか?
jlinkjdepsjmod
正解:2
jdeps(Java Dependency Analysis Tool) は、どのモジュールに依存しているかを静的に解析してくれます。
【例題⑨:カスタムJREの作成】
Q:必要なモジュールだけを組み合わせ、軽量なカスタム・ランタイムイメージを作成するツールはどれですか?
jdepsjlinkjavac
正解:2
jlinkを使うと、Java実行環境がないPCでも動く、最小限のサイズの実行イメージを書き出せます。
7. モジュール設定情報の調べ方
実際の開発や試験対策で「このモジュールには何が含まれているのか」「どのパッケージが公開されているのか」を確認したい場面があります。そのときに使うのが以下のコマンドです。
java –list-modules:利用可能なモジュール一覧を確認する
java --list-modules
JDKに含まれているすべてのモジュールの一覧が表示されます。java.baseやjava.sqlなど、どんなモジュールが存在するかを確認できます。
java –describe-module:特定モジュールの詳細を確認する
java --describe-module java.sql
指定したモジュールのrequires・exports・usesなどの設定内容をすべて表示します。「このモジュールは何に依存していて、何を公開しているか」を確認したいときに使います。
出力例:
java.sql@17
exports java.sql
exports javax.sql
requires java.base mandated
requires java.logging transitive
requires java.transaction.xa transitive
uses java.sql.Driver
この出力から「java.sqlはjava.baseを必須依存として持ち、java.loggingとjava.transaction.xaを推移的依存として持つ」ことがわかります。
jdeps –module-path:モジュールパスを指定して依存を解析する
jdeps --module-path mods -m myapp
自作モジュールの依存関係を解析するときに使います。--module-pathでモジュールの場所を指定し、-mで解析対象のモジュール名を指定します。
【例題⑩-補足:モジュール情報の確認】
Q:特定のモジュールのexports・requires・usesなどの設定内容を確認するためのコマンドはどれですか?
A. java --list-modules モジュール名
B. java --describe-module モジュール名
C. jdeps --describe モジュール名
D. jlink --info モジュール名
解説を見る
正解:B
--list-modulesは一覧表示のみで詳細は出ません。--describe-moduleを使うと指定モジュールのrequires・exports・usesなどの詳細設定をすべて確認できます。試験では「どのコマンドで何がわかるか」の使い分けが問われます。
8. モジュール境界を一時的に解除する:–add-modulesと–add-exports
モジュールシステムの厳格なカプセル化は便利な反面、「既存のライブラリが内部APIを使っていて動かない」「テスト時だけ非公開パッケージにアクセスしたい」という場面で困ることがあります。そのときに使うのが–add-modulesと–add-exportsです。
–add-modules:モジュールを明示的に追加する
java --add-modules java.xml.bind -jar myapp.jar
通常はmodule-info.javaのrequiresで依存を宣言しますが、module-info.javaを変更せずにモジュールを追加したい場合にコマンドライン引数で指定します。移行期に古いコードを動かすときなどに使われます。
複数指定する場合はカンマ区切りで指定します。
java --add-modules java.xml.bind,java.activation -jar myapp.jar
–add-exports:非公開パッケージへのアクセスを許可する
java --add-exports java.base/sun.security.x509=ALL-UNNAMED -jar myapp.jar
書き方は「モジュール名/パッケージ名=アクセスを許可するモジュール名」の形式です。
java.base/sun.security.x509:公開を許可するモジュールとパッケージALL-UNNAMED:無名モジュール(クラスパス上のコード)すべてに許可する特殊キーワード
特定のモジュールだけに許可する場合はALL-UNNAMEDの代わりにモジュール名を指定します。
java --add-exports java.base/sun.security.x509=com.example.mymodule -jar myapp.jar
–add-opens:リフレクションによるアクセスを許可する
java --add-opens java.base/java.lang=ALL-UNNAMED -jar myapp.jar
–add-exportsはコンパイル時・実行時のアクセスを許可しますが、–add-opensはリフレクションによるアクセスも含めて許可します。module-info.javaのopensをコマンドラインから動的に指定するイメージです。
| オプション | 用途 | 対応するmodule-info.javaの指令 |
|---|---|---|
| –add-modules | モジュールを明示的に追加する | requires |
| –add-exports | 非公開パッケージへのアクセスを許可する | exports … to … |
| –add-opens | リフレクションによるアクセスも含めて許可する | opens … to … |
【例題:–add-exportsの使い方】
Q:モジュールcom.example.app(無名モジュール上のコード)から、java.baseモジュールの非公開パッケージsun.utilにアクセスしたい場合、正しいコマンドライン引数はどれですか?
A. --add-exports sun.util=java.base/ALL-UNNAMED
B. --add-exports java.base/sun.util=ALL-UNNAMED
C. --add-modules java.base/sun.util
D. --add-opens sun.util/java.base=ALL-UNNAMED
解説を見る
正解:B
–add-exportsの書き方は「公開元モジュール名/パッケージ名=アクセス許可するモジュール名」の順番です。順番を逆に覚えないよう注意。無名モジュール(クラスパス上のコード)すべてに許可する場合はALL-UNNAMEDを使います。
【例題:–add-modulesと–add-exportsの違い】
Q:次の説明のうち正しいものはどれですか?
A. –add-modulesはパッケージの公開範囲を変更する
B. –add-exportsはモジュールをモジュールグラフに追加する
C. –add-modulesはmodule-info.javaを変更せずにモジュールを追加でき、–add-exportsは非公開パッケージへのアクセスを許可する
D. –add-modu
9. 高度な設定:サービス・ローダ
最後は少し難しい、インターフェースと実装の分離について。
【例題⑩:サービスの利用】
Q:モジュールが利用するサービス(インターフェース)を指定するキーワードはどれですか?
providesuseswith
正解:2
usesは利用側(ServiceLoaderなどを使う側)、provides ... with ...は実装を提供する側が使用します。
まとめ:モジュールシステム攻略のコツ
モジュールシステムは、一見難解ですが、module-info.javaの構文ルールさえ覚えてしまえば、Gold試験では確実に4〜5問は取れるボーナス分野です。
- requires/exports の向きを逆に覚えない。
- transitive の連鎖を理解する。
- jdeps/jlink の役割を混同しない。
この3点を意識して、黒本の問題を解き直してみてください。応援しています!

理解したら、問題で確認
Java Gold SE17のコード読解問題に挑戦する
この記事で学んだ内容を、Java Gold SE17向けの問題演習アプリで復習できます。 カテゴリ別問題と60問の模擬試験を、登録不要で利用できます。
Java Gold問題を解く →
コメント