最新のjava言語仕様で見るモジュールシステム #jjug
TRANSCRIPT
最新の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 JEPshttp://openjdk.java.net/projects/jdk9/
中でも超ビッグな変更のアイツ
Java PlatformModule 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/docs/api/java/lang/annotation/ElementType.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 で確認