Kodrill

Java モジュール・システム

Java SE 17 Gold (1Z0-826-JPN) 試験

モジュール型 JDK/module-info.java の requires・exports・opens/モジュールのコンパイルと実行/無名モジュール・自動モジュール/jdeps/ServiceLoader

問題数
18 問
合格ライン
65%
この分野の要点を読む7 章・約 11 分。実行して確かめたコード例と、試験でよくある引っかけをまとめています

ログインなしで試す

無料の 5 問を、1問ごとに正誤と解説を見ながら解けます。解答は保存されません。

5 問を試す

無料登録して学習を記録する

学習履歴・ダッシュボード・ブックマーク・模試モードが使えます。

★ 残り 13 問はプレミアム会員限定です

無料プランでは先頭 5 問まで解けます。プレミアムなら全問題・苦手問題の復習・広告非表示が使えます。
料金プランを見る

問題と解説を見る (無料)

登録しなくても、次の5問は問題文と解説をそのまま読めます。

Java モジュール・システムの要点

内容の確認日: 2026-10-04

この分野では、Java SE 9 で導入されたモジュール・システムの仕組みと、それを使うためのコマンドが問われます。module-info.java の各指示文の意味と、「モジュールの外から何が見えるか」のルールを正確に押さえることが中心です。コマンドのオプション (-p・-m など) も、短縮形まで問われます。

出題項目は「モジュール・システムの概要とモジュール型 JDK」「モジュールの宣言とモジュール間のアクセス」「モジュール化されたアプリケーションのコンパイルと実行」「無名モジュールおよび自動モジュールの使用」「jdeps の使用」「モジュール・システムにおける ServiceLoader の使用」の 6 つです。

モジュール型 JDK

Java SE 9 以降、JDK 自体が多数のモジュールに分割されています。java.lang・java.util・java.io などの基本的なパッケージを含む java.base は、すべてのモジュールが暗黙的に読み込むモジュールで、requires を書く必要はありません。java.sql (JDBC) や java.logging などは別のモジュールです。

Shell
java --list-modules               # JDK のモジュールの一覧java --describe-module java.sql   # モジュールの exports・requires などを表示 (短縮形は -d)

クラスがどのモジュールに属しているかは、Class の getModule() で確かめられます。クラスパスから読み込まれたクラス (下の例の Main) は、名前のない無名モジュールに属します。

Main.java
public class Main {    public static void main(String[] args) {        System.out.println(String.class.getModule().getName());        System.out.println(java.sql.Connection.class.getModule().getName());        System.out.println(Main.class.getModule().isNamed());        System.out.println(Main.class.getModule().getName());    }}
ターミナル
java Main
java.base
java.sql
false
null

module-info.java の宣言

モジュールは、ソースのルートに置いた module-info.java で宣言します。主な指示文は次のとおりです。

module-info.java
module com.example.shop {    requires java.sql;                        // java.sql モジュールを読み込む    requires transitive com.example.util;     // 自分を読み込むモジュールにも util を読み込ませる    exports com.example.shop.api;             // このパッケージを公開する    exports com.example.shop.internal to com.example.admin;  // 公開先を限定する (限定エクスポート)    opens com.example.shop.model;             // リフレクションでのアクセスを許可する}

モジュールの外から使えるのは、exports したパッケージの public な型 (とその public・protected なメンバー) だけです。exports していないパッケージの型は、public でも使えません。exports はコンパイル時と実行時のアクセスを許可し、opens は実行時のリフレクション (private メンバーへのアクセスを含む) を許可します。モジュール全体を開くときは open module 名前 { ... } と書きます。

requires transitive を使うと、依存が推移します。lib が requires transitive util と書いていれば、lib を requires した app も util を読み込めます (transitive がなければ、app は自分で requires util を書く必要があります)。

主な制約は次のとおりです。

・exports・opens にはパッケージ名を 1 つずつ書く。ワイルドカード (*) は使えない ・requires に書くのはモジュール名 (パッケージ名ではない) ・requires による依存関係が循環してはいけない (コンパイルエラー) ・同じパッケージを複数のモジュールが含むこと (分割パッケージ) はできない

コンパイルと実行

モジュールは、module-info.java と一緒にコンパイルします。実行するときは、モジュールを置いたディレクトリ (または JAR) を --module-path (短縮形 -p) で指定し、--module (短縮形 -m) で モジュール名/メインクラスの完全修飾名 を指定します。

Shell
# コンパイル (出力先にモジュールのディレクトリを作る)javac -d mods/com.example.app src/com.example.app/module-info.java src/com.example.app/com/example/app/Main.java​# 実行java -p mods -m com.example.app/com.example.app.Main

jar で JAR にまとめるときに --main-class を指定すると、実行時の -m ではモジュール名だけを書けば済みます。

Shell
jar --create --file mods/app.jar --main-class com.example.app.Main -C mods/com.example.app .java -p mods -m com.example.app

--add-modules は、依存関係から自動では解決されないモジュールを、起動時に追加で読み込むオプションです。

無名モジュールと自動モジュール

モジュール化されていないコードとモジュールを組み合わせるために、2 種類の特別なモジュールがあります。

無名モジュール: クラスパスに置いたクラスや JAR は、すべて 1 つの無名モジュールにまとめられます。無名モジュールは、すべてのパッケージを公開し、すべてのモジュールを読み込みます。ただし名前がないので、名前付きモジュールから requires することはできません。

自動モジュール: module-info.class のない従来の JAR をモジュール・パスに置くと、自動モジュールになります。自動モジュールは、すべてのパッケージを公開し、すべてのモジュール (無名モジュールを含む) を読み込みます。名前付きモジュールから requires できます。名前は次のように決まります。

・JAR の META-INF/MANIFEST.MF に Automatic-Module-Name があれば、その名前 ・なければ JAR のファイル名から決める。拡張子とバージョン番号 (-1.2 など) を除き、英数字以外の文字を . に置き換える (例: my-util-1.2.jar → my.util)

既存のライブラリを段階的にモジュール化するときは、まだモジュール化されていない JAR をモジュール・パスに置いて自動モジュールとして使う、という移行の方法 (ボトムアップ・トップダウン) がとれます。

jdeps による依存関係の分析

jdeps は、コンパイル済みのクラスファイルや JAR を静的に解析して、どのパッケージ・モジュールに依存しているかを表示するツールです。プログラムは実行しません。モジュール化の準備として、依存関係を調べるのに使います。

Shell
jdeps -s app.jar                # 依存しているモジュールの概要 (-summary)jdeps --jdk-internals app.jar   # JDK の内部 API (今後使えなくなる可能性がある) への依存を表示

ServiceLoader とサービス

モジュール・システムでは、インタフェース (サービス) と、その実装 (サービス・プロバイダ) を別のモジュールに分け、実行時に実装を見つけて使えます。

module-info.java
// サービスのインタフェースを公開するモジュールmodule com.example.spi {    exports com.example.spi;          // Greeter インタフェースを含む}​// 実装を提供するモジュールmodule com.example.impl {    requires com.example.spi;    provides com.example.spi.Greeter with com.example.impl.JapaneseGreeter;}​// サービスを使うモジュールmodule com.example.app {    requires com.example.spi;    uses com.example.spi.Greeter;}

サービスを使う側は、ServiceLoader.load(Greeter.class) で実装を探します。ServiceLoader は Iterable なので、拡張 for 文で実装を順に取り出せます。findFirst() は最初の実装を Optional で返し、実装が 1 つもなければ空の Optional になります (例外にはなりません)。stream() で Stream として扱うこともできます。

Java
ServiceLoader<Greeter> loader = ServiceLoader.load(Greeter.class);for (Greeter g : loader) {    System.out.println(g.greet());}Greeter first = loader.findFirst().orElseThrow();

provides ... with に書く実装クラスには、public な引数なしのコンストラクタか、public static な provider() メソッドが必要です。使う側のモジュールは、実装のモジュールを requires しなくて構いません。

試験でよくある引っかけ

  • java.base の requires

    java.base はすべてのモジュールが暗黙的に読み込むので、requires は不要です。

  • exports していないパッケージ

    public なクラスでも、パッケージを exports していなければモジュールの外から使えません。

  • requires transitive

    transitive を付けると、自分を requires したモジュールにも依存先が読み込まれます。付けなければ推移しません。

  • -p と -m

    -p は --module-path、-m は --module の短縮形です。-m には モジュール名/クラス名 を書きます。

  • 無名モジュールを requires

    クラスパス上のコード (無名モジュール) は、名前付きモジュールから requires できません。モジュール・パスに置けば自動モジュールになり、requires できます。

  • provides と uses

    実装を提供する側が provides サービス with 実装、使う側が uses サービス を書きます。逆にしないよう注意。

問題で確認する

この分野の問題を、解説つきで読めます (登録不要)。

出典・参考

コード例は、試験の対象バージョンで実際にコンパイル・実行して結果を確認しています。