最新のJava言語仕様
で見るモジュールシステム
from The Java® Language Specification
Java SE 9 Edition
JJUG ナイト・セミナー
2017/12/27
自己紹介
• 株式会社ジャストシステム 福嶋 航
• Twitter @fukushiw
• Java歴約20年、JavaでWebサービス作っています
• #Java100 本ノックの人
https://github.com/JustSystems/java-100practices
本資料に出てくる内容は特に断りがない場合すべて、
The Java® Language Specification Java SE 9 Edition
https://docs.oracle.com/javase/specs/jls/se9/html/index.html
(2017年12月22日現在)
に記載されている内容をベースにしております。
あれ、おかしいな? と思ったら
上記原典をご覧下さい。
最新のJava言語仕様
で見るモジュールシステム
Java SE 9
91 JEPs
http://openjdk.java.net/projects/jdk9/
中でも超ビッグな
変更のアイツ
Java Platform
Module System
(JSR 376)
http://openjdk.java.net/projects/jigsaw/spec/
Java言語仕様に
どう記載されたか
を追いかけてみた
https://docs.oracle.com/javase/specs/jls/se9/html/index.html
(snip)
If a set of packages is sufficiently cohesive, then
the packages may be grouped into a module. (snip)
Thus, a module controls how its packages use
other modules (by specifying dependences) and
controls how other modules use its packages (by
specifying which of its packages are exported).
(snip)
• 十分に凝集されたパッケージセットはモジュールとして
グループ化されうる
• モジュールは他のモジュールをどう使うか、他のモジュー
ルからどう使われるかを制御する
Chapter 7. Packages and Modules
ModuleDeclaration:
{Annotation} [open] module Identifier {. Identifier} { {ModuleDirective} }
ModuleDirective:
requires {RequiresModifier} ModuleName ;
exports PackageName [to ModuleName {, ModuleName}] ;
opens PackageName [to ModuleName {, ModuleName}] ;
uses TypeName ;
provides TypeName with TypeName {, TypeName} ;
RequiresModifier:
(one of)
transitive static
7.7. Module Declarations
ModuleDeclaration:
{Annotation} [open] module Identifier {. Identifier} { {ModuleDirective} }
ModuleDirective:
requires {RequiresModifier} ModuleName ;
exports PackageName [to ModuleName {, ModuleName}] ;
opens PackageName [to ModuleName {, ModuleName}] ;
uses TypeName ;
provides TypeName with TypeName {, TypeName} ;
RequiresModifier:
(one of)
transitive static
7.7. Module Declarations
せっかくなので比較的出現頻度が低そうなやつらを調べてみた
{Annotation}
• ElementType に追加されている
https://docs.oracle.com/javase/9/doc
s/api/java/lang/annotation/ElementT
ype.html#MODULE
• JDK 9.0.1 で、アノテーションのタイプに
MODULE が出現するのは、 @Deprecated
と @SuppressWarnings の2つ
open
コンパイル時 実行時
open
明示的にexport
宣言されたパッ
ケージへのアクセ
スを許可
全パッケージへの
アクセスを許可
非
open
明示的にexport宣言されたパッケー
ジへのアクセスを許可
opens
コンパイル時 実行時
opens
アクセス不許
可
1.public/protectedな型とその
型のpublic/protectedなメン
バーへのアクセスを許可
2.すべての型とメンバーへのリフレク
ションアクセスを許可
exports
1.public/protectedな型とその型の
public/protectedなメンバーへのアクセスを
許可
2.それらの型とメンバーへのリフレクションアクセス
を許可
transitive
• requires につけて使う
例)requires transitive java.desktop;
• requires transitive の定義があるモジュール(例:m.B)を
requiresしているモジュール(例:m.A)が、暗黙的にその定義さ
れているモジュール(例:m.C)をrequiresしていることになる
module m.A {
requires m.B;
}
module m.B {
requires transitive m.C;
}
module m.C {
exports p;
}
モジュール m.A の
コードから
パッケージ p のコー
ドが呼び出せる
static
• requires につけて使う
例)requires static hogehoge;
• コンパイル時には依存が必須だが、実行時
には必須ではないことを示す
• JDK 9.0.1 のソースには出現しない
• lombokのようにコンパイル時のみ必要な
アノテーションを使うときとかに使う?
(ついでに) module-info.java
• ソースのルートディレクトリに置く
例)com.example.hoge パッケージを使う場合、comフォルダのあるディ
レクトリにmodule-info.javaを格納する。
src
├ module-info.java
└ com
  └ example
    └ hoge
      └ Main.java
• 正しくモジュールが作成できたかどうか確認する
 例) jar -d -f modulehoge.jar
「モジュール・ディスクリプタが見つかりません。自動モジュールが導出されまし
た。」というメッセージが出た場合、 module-info が正しく定義できていない。
これは言語仕様に
は書いていないので
実際にやってみた
まとめ
• モジュールシステムの仕様は Java言語仕様 (Java SE 9 Edition) で確認できる
• 7章、特に7.7節にメインの説明がある
• モジュールにつけられるアノテーションタイプ(MODULE)が追加されている
• JDK 9.0.1 では @Deprecated と @SuppressWarnings がある
• module の前に open がつくと:
• コンパイル時、明示的にexport宣言されたパッケージへのアクセスを許可
• 実行時、全パッケージへのアクセスを許可
• opens ディレクティブがついているパッケージは:
• コンパイル時にはアクセス不許可
• 実行時にはpublic/protectedな型とその型のpublic/protectedなメンバーへ
のアクセスを許可;すべての型とメンバーへのリフレクションアクセスを許可
• requires transitive しているモジュールは、その宣言をしているモジュールをrequires
しているモジュールからも(直接のrequires宣言をしなくても)呼び出せるようになる
• requires static しているモジュールは、コンパイル時のみ依存するが実行時にはなくて
もよい
• module-info.java はソースのルートディレクトリに置く
• 正しくモジュールが作成できたかどうかは jar -d -f modulehoge.jar で確認

最新のJava言語仕様で見るモジュールシステム #jjug