Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java SE 8から11で何が起きた?一気におさらいしてみよう! /java-se-8-to-11

Java SE 8から11で何が起きた?一気におさらいしてみよう! /java-se-8-to-11

Introduces changes in Java SE and its ecosystem, from Java SE 8 to 11.

Miyakawa Taku

December 23, 2018
Tweet

More Decks by Miyakawa Taku

Other Decks in Programming

Transcript

  1. Java SE 8から11で何が起きた?
    一気におさらいしてみよう!
    2018-12-23 Java女子部 #javajo
    宮川 拓
    本文書の利用をCC BY 4.0 にもとづいて許諾します

    View Slide

  2. ⚫ @miyakawa_taku
    ⚫ JJUG幹事
    ⚫ Salesforceで働いています
    ⚫ 奄美出身の力士が好きです☆
    ⚫ オレオレJVM言語Kinkを作っています
    https://bitbucket.org/kink/kink
    自己紹介
    #javajo
    2/137

    View Slide

  3. 本セッションのあらまし
    ⚫ Java SE 8からJava SE 11に掛けて、
    たくさんのことが起こりました
    ◼ JDKのリリースモデル変更
    ◼ モジュールシステムの導入
    ◼ 各種機能の追加・変更・廃止・切り離し
    ⚫ 何が起きたのか把握して、
    安心して11+に踏み出しましょう☆
    ⚫ とはいえ
    #javajo
    3/137

    View Slide

  4. とはいえ
    ⚫ たいへんな道のりであることは確かです
    #javajo
    4/137

    View Slide

  5. 本セッションの基調低音
    ⚫ Javaは変わりつつある
    ⚫ Write Once Run Anywhereの担い手という
    役割は縮小している
    ⚫ 一方で、サーバサイド処理系としての
    進化はペースを上げている
    #javajo
    5/137

    View Slide

  6. 演目
    Java SE, JDKってなんだっけ
    Java SEをとりまく環境の変化
    モジュールシステムとjlink
    #javajo
    6/137

    View Slide

  7. スコープ
    主に触れること
    ◼ Java処理系関連のざっくりした傾向
    ◼ モジュール関連の機能
    触れないこと
    ◼ 実装固有の機能: GC, 内部処理改善等
    ◼ 外部ツール・ライブラリの対応状況
    → Migration Guide from Java 8 to Java 11
    by 久保田さん
    #javajo
    7/137

    View Slide

  8. #javajo
    ハンズオン
    Linux, macOS用ハンズオン
    ◼ https://quip.com/axDqAMIbZjnR/Java-
    11-Linux-macOS
    Windows用ハンズオン
    ◼ https://quip.com/edM1AVI5xssC/Java-
    11-Windows
    8/137

    View Slide

  9. 演目
    Java SE, JDKってなんだっけ
    Java SEをとりまく環境の変化
    モジュールシステムとjlink
    #javajo
    9/137

    View Slide

  10. Java SEとは
    Java SE: Java処理系の規格
    ◼ 正式名称: Java Standard Edition
    ◼ 規格の中身:
    ◆ 言語仕様
    ◆ Java仮想マシンの仕様
    ◆ 標準APIの仕様
    ◼ 代表的な実装: OpenJDK, Oracle JDK等
    #javajo
    10/137

    View Slide

  11. Java SEタイムライン
    invokedynamic
    ラムダ式, Stream API
    モジュール・システム (a.k.a. Jigsaw)
    2011.07
    Java SE 7
    2014.03
    Java SE 8
    2017.09
    Java SE 9
    2018.03
    Java SE 10
    var記法
    Functional Java
    基盤の大改造
    2018.09
    Java SE 11
    Appletの削除
    ServiceLoader
    2006.12
    Java SE 6
    #javajo
    11/137

    View Slide

  12. Java SEの規格開発プロセス
    Java Community Process (JCP)
    ◼ 正式な規格化プロセス
    ◼ Expert Groupによるドラフト提出、
    Executive Committeeの投票を通して、
    個々の仕様であるJSRを策定
    ◼ Java MEやEEも対象(だった)
    ◆ Jakarta EEは対象外
    ◼ きっちりしたはる
    #javajo
    12/137

    View Slide

  13. Java SEの規格開発プロセス
    JDK Enhancement Proposal (JEP)
    ◼ OpenJDKの開発プロセス
    ◼ 主にML内で合意形成される
    ◼ Python Enhancement Proposalがお手本
    ◼ 2011年以降、実質的にはJEPが規格化を
    引っ張る
    ◼ Java SEの規格に入らない、実装固有の
    機能(例: GC方式)も議論の対象
    #javajo
    13/137

    View Slide

  14. Java SE 9, 10, 11
    モジュール以外の主な新機能
    #javajo
    14/137

    View Slide

  15. Java SE 9: JEP 269
    コレクションのファクトリ
    #javajo
    15/137

    View Slide

  16. コレクションのファクトリ
    List.of, Set.of, Map.ofメソッドで、不変な
    コレクションが作れるようになりました☆
    #javajo
    16/137

    View Slide

  17. List.of
    List a
    = Collections.emptyList();
    List b
    = Collections.singletonList("foo");
    List c
    = Collections.unmodifiableList(Arrays.asList("foo", "bar"));
    List a = List.of();
    List b = List.of("foo");
    List c = List.of("foo", "bar");
    ~Java SE 8
    Java SE 9~
    #javajo
    17/137

    View Slide

  18. Map.of
    Map m = new HashMap<>();
    m.put("双葉山", 69);
    m.put("大鵬", 45);
    m.put("白鵬", 63);
    Map yokozuna
    = Collections.unmodifiableMap(m);
    ~Java SE 8
    Map yokozuna
    = Map.of("双葉山", 69, "大鵬", 45, "白鵬", 63);
    Java SE 9~
    #javajo
    18/137

    View Slide

  19. Java SE 9: JEP 213
    try-with-resourcesの改善
    #javajo
    19/137

    View Slide

  20. try-with-resourcesの改善
    try (BufferedReader br = new BufferedReader(
    new InputStreamReader(
    new FileInputStream("foo.txt"),
    StandardCharsets.UTF_8))) {
    ...
    }
    ~Java SE 8
    Java SE 9~
    BufferedReader br = new BufferedReader(
    new InputStreamReader(
    new FileInputStream("foo.txt"),
    StandardCharsets.UTF_8));
    try (br) {
    ...
    }
    #javajo
    20/137

    View Slide

  21. Java SE 9: JEP 226
    ResourceBundleプロパティが
    デフォルトUTF-8に☆
    #javajo
    21/137

    View Slide

  22. ResourceBundle→UTF-8
    ~Java SE 8
    Java SE 9~
    ⚫ ResourceBundleのプロパティファイルは
    デフォルトでLatin-1
    ⚫ 日本語などのメッセージはnative2asciiで
    エスケープする必要があった
    ⚫ ResourceBundleのプロパティファイルが
    デフォルトでUTF-8に☆
    ⚫ 注意: Propertiesクラスのデフォルトは
    Latin-1のまま
    #javajo
    22/137

    View Slide

  23. Java SE 10, 11: JEP 286, 323
    var記法
    #javajo
    23/137

    View Slide

  24. var記法
    var トリオ漫才 = List.of(
    "横山ホットブラザーズ", "かしまし娘", "宮川左近ショー");
    トリオ漫才.forEach(System.out::println);
    Java SE 10, 11
    Listトリオ漫才 = List.of(
    "横山ホットブラザーズ", "かしまし娘", "宮川左近ショー");
    トリオ漫才.forEach(System.out::println);
    Java SE 9
    ローカル変数宣言で型が省略できるように
    #javajo
    24/137

    View Slide

  25. Java SE 11: JEP 320
    サーバ向け機能の削除
    #javajo
    25/137

    View Slide

  26. サーバ向け機能の削除
    Java SE 11で削除された主なサーバ向け機能:
    ◼ ドロップインの代替ライブラリあり
    ◆ JAXBのAPIとデフォルト実装
    ◆ JAX-WSのAPI
    ◆ JTAのAPI
    ◼ ドロップインの代替ライブラリなし
    ◆ CORBA
    → 該当機能を使用中の場合、移行時に要対応
    #javajo
    26/137

    View Slide

  27. Java SE 11
    デスクトップ向け機能の削除
    #javajo
    27/137

    View Slide

  28. デスクトップ向け機能の削除
    Java SE 11でApplet*が削除
    ◼ 主要ブラウザはNPAPI廃止済みのため、
    既に使えなくなっていた
    ◼ ブラウザプラグイン自体が下火
    Flash, Silverlightも廃止予定
    ◼ HTML5時代の必然
    #javajo
    * Applet: ブラウザプラグイン上で動く Java プログラム。
    Flashみたいな感じ
    28/137

    View Slide

  29. デスクトップ向け機能の削除
    Oracle JDK 11はJavaFX*1とJava Web Start*2
    を同梱しなくなった
    ※ 両方もともとJava SE仕様範囲外
    ※ ただしWeb Startには関連仕様として
    JSR 56: JNLPがある
    ◼ JavaFXはOpenJFXプロジェクトで
    開発継続中
    #javajo
    * 1 JavaFX: GUIライブラリ。 SwingとかQtみたいなやつ
    * 2 Java Web Start: リンクを押すと Java プログラムが
    落ちてきてPC上 で実行される仕組み
    29/137

    View Slide

  30. どうなるJavaデスクトップ?
    ⚫ Javaデスクトップ環境にとっては
    大きな転換点
    ◼ 参考: https://aoe-tk.hatenablog.com/en
    try/2018/03/11/203708
    ⚫ 転換には、Public JREの廃止が密接に関連
    → 次章!
    #javajo
    30/137

    View Slide

  31. 演目
    Java SE, JDKってなんだっけ
    Java SEをとりまく環境の変化
    モジュールシステムとjlink
    #javajo
    31/137

    View Slide

  32. Java SEをとりまく環境の変化
    Java SE 8から11にかけての大変動:
    ◼ OpenJDK, Oracle JDKの
    リリースサイクル変更(Java 9~)
    ◼ Oracle JDKのライセンス変更
    (Java 11~)
    ◼ Public JRE配布の廃止
    (Java 11~)
    ◼ OpenJDKエコシステムの活発化
    #javajo
    32/137

    View Slide

  33. OpenJDK, Oracle JDKの
    リリースサイクル変更
    #javajo
    33/137

    View Slide

  34. リリースサイクル変更
    ~Java SE 8
    Java SE 9~
    2006.12
    Java SE 6
    2011.07
    Java SE 7
    2014.03
    Java SE 8
    4 年半 2 年半
    2017.09
    Java SE 9
    2018.03
    Java SE 10
    2018.11
    Java SE 11
    2019.03
    Java SE 12
    2019.11
    Java SE 13
    仕様が固まったら
    リリース
    半年ごとに
    リリース
    #javajo
    34/137

    View Slide

  35. 私見
    時間で切ってリズムを作ることの有益さは
    実証されている
    ◼ Scrum
    ◼ Ubuntu
    ◼ JJUGも!
    開発の観点でのメリットは大きい
    望むらくはエコシステム全体にとっても
    #javajo
    35/137

    View Slide

  36. Oracle JDKのライセンス変更
    #javajo
    36/137

    View Slide

  37. Oracle JDKのライセンス変更
    ~Java 10
    ◼ 公開で配布されるOracle JDKは、
    BCLのもとに利用が許諾された
    ◆ 開発・本番運用ともに利用OK
    ◆ リバースエンジニアリングはダメ
    #javajo
    37/137

    View Slide

  38. Oracle JDKのライセンス変更
    Java 11~
    ◼ OTNライセンスに変更
    ◆ 開発用途の利用はOK
    ◆ 本番用途はダメ
    ◼ 本番用途でOracle JDKを使うには、
    サブスクリプションの契約が必要
    ※ 3年ごとのLTS版(11, 17, ...)に、
    半年を超えてパッチが提供される
    #javajo
    38/137

    View Slide

  39. かわりにOpenJDKを使えば良い?
    ⚫ もちろん!
    ⚫ OpenJDKのライセンスはGPLv2+CPE
    つまり自由に利用・改変・再配布できる
    ⚫ Oracle JDKと中身はほとんど同じ
    ⚫ ただし、本家サイトでのバイナリ配布は
    ◼ x86-64版のみ
    ◼ zip/tar.gzアーカイブのみ
    #javajo
    39/137

    View Slide

  40. Public JRE配布の廃止
    #javajo
    40/137

    View Slide

  41. WORA!
    ⚫ Javaのプログラムはどこでも動く
    Write Once, Run Anywhere!
    ⚫ OSがUnixでもWindowsでも
    ⚫ CPUがx86でもSparcでもARMでも
    ⚫ ただし、Javaがインストールされていれば
    #javajo
    41/137

    View Slide

  42. WORAの前提としてのPublic JRE
    ⚫ Public JREは、一般ユーザ向けに
    Sun/Oracleが配布していたJava処理系
    ◼ 「あなたとJAVA, 今すぐダウンロード」
    ⚫ AppletプラグインやJava Web Startも含む
    → いずれもJava SE 11で廃止
    ⚫ Java SE 11では、
    Public JREの配布が廃止された
    #javajo
    42/137

    View Slide

  43. 時代の終わり
    ⚫ 「どこでもJavaが入っている」時代は
    終わった
    ◼ iPhone登場時点で終わっていたのかも
    ◼ 今はむしろ、ブラウザとJavaScriptが
    WORAの担い手
    #javajo
    43/137

    View Slide

  44. 今後のJavaプログラム配布
    ⚫ 今後Javaプログラムは、jlinkなどを使って、
    Java処理系ごと配布する方式が
    模索されている
    ◼ モジュールシステムが密接に関連
    → 次章!
    #javajo
    44/137

    View Slide

  45. OpenJDKエコシステムの
    活発化
    #javajo
    45/137

    View Slide

  46. OpenJDKエコシステムの活発化
    Java SE自体の進歩は、OpenJDKを中心に、
    むしろ活発になっている
    ◼ クラウド・サーバサイド向けの
    開発が加速
    ◼ 多様なOpenJDKディストリビューション
    の登場
    #javajo
    46/137

    View Slide

  47. OpenJDK
    OpenJDK (https://openjdk.java.net/)
    ◼ Java SEの参照実装(RI)
    ◼ ライセンス: GPLv2+Classpath Exception
    ◼ コントリビュータ:
    ◆ Oracle, Red Hat, IBM, Azul, Amazon ..
    ◆ @YaSuenag, @sugarlife, @shinyafox ..
    ◼ Oracle JDKの商用機能が多くマージされ、
    ほぼ同じ中身になった
    #javajo
    47/137

    View Slide

  48. 開発の加速
    加速するOpenJDK開発
    ◼ たくさんの新GC方式
    ◆ G1GC, ZGC, Shenandoah
    ◼ 起動時間の改善
    ◆ Class Data Sharing, AOT Compilation
    ◼ フットプリント削減: jlink
    ◼ 新JITコンパイラ: Graal
    ◼ 新仕様群: Panama, Vallhara, Loom, ...
    #javajo
    48/137

    View Slide

  49. OpenJDKディストロ
    素のOpenJDKを使うのはハードルが高い
    ◼ バイナリ提供: x86-64版のみ
    ◼ パッケージング: zip/tar.gzアーカイブ
    → 各種OpenJDKディストリビューションに
    注目が集まる
    #javajo
    49/137

    View Slide

  50. OpenJDKディストロ
    ⚫ AdoptOpenJDK
    ⚫ Red Hat OpenJDK
    ⚫ Azul Zulu
    ⚫ Amazon Corretto
    #javajo
    50/137

    View Slide

  51. #javajo
    AdoptOpenJDK
    ⚫ AdoptOpenJDK
    ⚫ 様々なプラットフォーム向けに
    OpenJDKをビルド・テストして提供する、
    コミュニティベースのプロジェクト
    ⚫ Windows (x86, x86-64), Mac,
    Linux (x86-64, Power, ARM64)
    ⚫ LTS版は最短4年アップデートを提供
    51/137

    View Slide

  52. #javajo
    Red Hat OpenJDK
    ⚫ Red HatによるOpenJDKパッケージ
    ⚫ GC実装としてShenandoahが含まれる
    ⚫ Red Hat Enterprise Linux, Windows
    ⚫ 提供バージョンを最短6年アップデート
    ⚫ 商用サポートあり
    52/137

    View Slide

  53. #javajo
    Azul Zulu
    ⚫ Zulu
    ⚫ Java処理系専業企業であるAzul Systemsが
    提供するディストロ
    ⚫ Windows (x86-64), Mac,
    Linux (x86-64, ARM64)
    ⚫ LTS版について8年アップデート
    ⚫ 商用サポートあり
    53/137

    View Slide

  54. #javajo
    Amazon Corretto
    ⚫ Amazon Corretto
    ⚫ Amazon Linuxにバンドルしていた
    OpenJDKをパッケージ化したもの
    ⚫ Windows (x86, x86-64), Mac,
    Linux (x86-64)
    ⚫ 2018年12月時点でOpenJDK 11は未提供
    54/137

    View Slide

  55. 注意! Ubuntu公式パッケージ
    ⚫ Ubuntu 18.04 のopenjdk-ltsパッケージは
    OpenJDK 10にセキュリティパッチを適用
    したもの
    (2018年12月時点)
    ⚫ Bug #1796027
    #javajo
    55/137

    View Slide

  56. Q. 結局なにを使えば良いの?
    #javajo
    56/137

    View Slide

  57. #javajo
    Q. 結局なにを使えば良いの?
    A. 場合による
    要件として検討するべき項目:
    ◼ Javaを動かすプラットフォームは?
    ◼ 何年後にメジャーアップデートする?
    ◼ パッチ適用の頻度・機会・方式は?
    ◼ 商用サポートは必要?
    ◼ ……
    57/137

    View Slide

  58. Javaをとりまく環境の変化
    小まとめ
    #javajo
    58/137

    View Slide

  59. #javajo
    Javaをとりまく環境の変化
    ⚫ Javaはえらい勢いで変わっている
    ◼ 昔: いつでもどこでも動く夢の処理系
    ◼ 今: 実用的で先鋭的なサーバサイド環境
    ⚫ 使う側も実用的で先鋭的になる必要がある
    59/137

    View Slide

  60. 演目
    Java SE, JDKってなんだっけ
    Java SEをとりまく環境の変化
    モジュールシステムとjlink
    #javajo
    60/137

    View Slide

  61. モジュール・システム
    このセクションの目的:
    ◼ モジュール・システム対応に向けて、
    心の準備ができること
    #javajo
    61/137

    View Slide

  62. モジュール・システム
    内容:
    ◼ モジュール・システム導入の背景
    ◼ モジュール・システムの基本
    ◼ リフレクション
    ◼ コンパイルと実行
    ◼ モジュール世界への移行
    ◼ モジュールのテスト
    ◼ jlink
    ◼ 高度なトピック
    #javajo
    62/137

    View Slide

  63. モジュール・システム
    導入の背景
    #javajo
    63/137

    View Slide

  64. Java 8までの課題
    ⚫ JAR地獄
    ⚫ 「内部向けパッケージ」の存在
    ⚫ Java処理系の肥大化
    #javajo
    64/137

    View Slide

  65. JAR地獄
    #javajo
    65/137

    View Slide

  66. ~Java 8: JAR地獄
    ⚫ JAR地獄 := 大量のJARがクラスパスに
    展開されて、混沌にブチ込まれること
    ◼ 「このJARいらないんじゃない?」
    ◼ → 消したら実行時エラー
    ⚫ Maven, Gradleのような依存性管理
    ツールを使えば少しはマシだけど……
    #javajo
    66/137

    View Slide

  67. ~Java 8: JAR地獄
    複数バージョン混在地獄
    ゲ ー ム Ace Shooter
    matrix-1.0.0.jar
    matrix-impl-2.0.0.jar
    matrix-api-2.0.0.jar
    physics.jar
    名前の異なるMavenアーティファクトが
    同じパッケージ/クラスを含む場合があり得る
    org.example.matrix.api.*
    org.example.matrix.impl.* org.example.matrix.api.*
    org.example.matrix.impl.*

    #javajo
    67/137

    View Slide

  68. 内部向けパッケージ
    #javajo
    68/137

    View Slide

  69. ~Java 8: 内部向けパッケージ
    ⚫ プラットフォームやライブラリ内で、
    「内部向け」パッケージを作ることがある
    ◼ org.kink_lang.kink.internal.xxx
    ◼ sun.misc (JDK内)
    ⚫ 内部向けパッケージは本来、ライブラリ外
    からの使用を想定していない
    ⚫ が、しかし
    #javajo
    69/137

    View Slide

  70. ~Java 8: 内部向けパッケージ
    GitHubで“import sun.misc.Unsafe”を検索
    #javajo
    70/137

    View Slide

  71. ~Java 8: 内部向けパッケージ

    #javajo
    71/137

    View Slide

  72. ~Java 8: 内部向けパッケージ
    ⚫ 内部使用向けのはずのUnsafeクラスが広く
    使われてしまっている
    ◼ 性能を絞り出すため……
    ⚫ なにが問題か?
    ◼ 移植性の低いプログラムの蔓延
    ◼ 既存のプログラムを壊さないように配慮
    すると、実装の改善がしづらい
    #javajo
    72/137

    View Slide

  73. Java処理系の肥大化
    #javajo
    73/137

    View Slide

  74. #javajo
    従来のサーバサイドデプロイ方式
    従来はAPサーバにWAR/EARを置いていた
    Java処理系(OpenJDK等)
    APサーバ(Glassfish, JBoss等)
    WAR/EARファイル
    OS(カーネル+ユーザランド)
    こ こ の サ イ ズ は
    大 し て 気 に し な い
    74/137

    View Slide

  75. #javajo
    最近のサーバサイドデプロイ方式
    最近はJava処理系を含むコンテナをデプロイ
    OS(カーネル+ユーザランド)
    コンテナホスト(Docker等)
    コンテナ
    OS(ユーザランドのみ)
    Java処理系(OpenJDK等)
    JARファイル
    サイズが大きいと
    デプロイが苦しい
    75/137

    View Slide

  76. ~Java 8: Java処理系の肥大化
    #javajo
    42MB
    68MB
    146MB
    177MB
    Java SE 5 Java SE 6 Java SE 7 Java SE 8
    Oracle JDKのダウンロードサイズ
    ※いずれもx86-64版の最新バージョン

    76/137

    View Slide

  77. #javajo
    ~Java 8: Java処理系の肥大化
    アプリが使う機能はJava処理系のごく一部
    ◼ サーバサイドアプリにSwingは不要
    ◼ 制御系組込みシステム以外でCORBAが
    使われることはまれ
    使わない機能がフットプリントの大部分を
    占めることはやるせない
    77/137

    View Slide

  78. モジュール・システムの基本
    #javajo
    78/137

    View Slide

  79. モジュール・システム
    ⚫ JARを名前付きのモジュールとして、
    カプセル化された配置の単位に
    ⚫ JAR地獄
    → モジュール単位で依存関係を整理
    ⚫ 内部向けパッケージ
    → 外部からの使用を実質的に制限
    ⚫ Java処理系の肥大化
    → jlinkでカスタムのJava処理系を作成
    #javajo
    79/137

    View Slide

  80. モジュール・システム
    各JARファイルが名前付きのモジュールに
    ace-shooter.jar
    = module net.example.ace_shooter
    matrix.jar
    = module org.example.matrix
    physics.jar
    = module jp.example.physics
    モジュール名は逆ドメイン名方式が推奨
    #javajo
    80/137

    View Slide

  81. パッケージ衝突の検知
    module net.example.ace_shooter
    module org.example.matrix
    module
    org.example.matrix.impl
    module
    org.example.matrix.api
    module jp.example.physics
    複数のモジュールが同一パッケージを含む場合、
    起動時に検知される †
    org.example.matrix.impl.*
    org.example.matrix.api.* org.example.matrix.api.*
    org.example.matrix.impl.*

    #javajo
    81/137

    View Slide

  82. module-info.java
    モジュール名はソースディレクトリのトップ
    レベルのmodule-info.javaで宣言
    module org.example.matrix {
    }
    JARファイルのトップレベルの
    module-info.class
    コンパイル
    #javajo
    82/137

    View Slide

  83. 公開パッケージの指定
    module org.example.matrix {
    exports org.example.matrix.api;
    }
    モジュールは、他のモジュールに対して公開
    するパッケージをexports命令で指定する
    exportされたパッケージは
    モジュールの外部仕様 の一部とみなせる
    #javajo
    83/137

    View Slide

  84. 使うモジュールの指定
    module jp.example.physics {
    requires org.example.matrix;
    }
    モジュールは、自分が使うモジュールを、
    requires命令で指定する
    モジュールが使えるクラスの条件:
    ⚫ requiresした先のモジュールの
    ⚫ exportsされたパッケージの
    ⚫ publicなクラス
    → 該当しないクラスを使うと
    コンパイルエラー / 実行時例外
    #javajo
    84/137

    View Slide

  85. exports / requires
    module A {
    requires B;
    }
    module B {
    exports B.api;
    requires C;
    }
    module C {
    exports C.api;
    }
    B.apiパッケージ
    B.implパッケージ
    C.apiパッケージ
    →使える
    →使えない
    →使えない
    C.apiパッケージ →使える
    #javajo
    85/137

    View Slide

  86. exports / requires
    module A {
    requires B;
    }
    module B {
    exports B.api;
    requires C;
    }
    module C {
    exports C.api;
    }
    A.xxxパッケージ →使える
    自分のモジュール内のパッケージは、非公開でも使える
    B.xxxパッケージ
    C.xxxパッケージ →使える
    →使える
    #javajo
    86/137

    View Slide

  87. exports / requires
    module A {
    requires B;
    }
    module B {
    exports B.api;
    requires C;
    }
    requiresしたモジュールが存在しないと
    コンパイルエラー / 実行時例外
    #javajo
    87/137

    View Slide

  88. 標準モジュール
    Java SEの標準ライブラリも、モジュールに
    分割されている
    ⚫ java.baseモジュールは暗黙的にrequiresされる
    ⚫ それ以外は明示的にrequiresする必要あり
    モジュール パッケージ群
    java.base java.lang, java.util, java.io, ...
    java.sql java.sql, javax.sql, ...
    java.desktop java.awt, javax.swing, ...
    ... ...
    #javajo
    88/137

    View Slide

  89. リフレクション
    #javajo
    89/137

    View Slide

  90. リフレクション
    モジュールのカプセル化はリフレクションに
    も適用される
    ◼ 外部モジュールからアクセスできるのは、
    exportsされたパッケージの、
    公開クラスの、
    公開メンバだけ
    ◆ requires関係は不要
    ◼ 非公開なメンバへのアクセスは、
    外部モジュールからは通常不可能
    #javajo
    90/137

    View Slide

  91. リフレクション
    困る例: DI先のクラス
    package net.example.ace_shooter.engine;
    public class GameEngine {
    @Inject private PerfMonitor perfMonitor;
    ...
    }
    public にしたくない
    exportsしたくない
    リフレクションで触ってほしいクラスは
    必ずしも公開したいわけではない
    #javajo
    91/137

    View Slide

  92. リフレクション
    必要な緩和策:
    ◼ パッケージをexportsしたくない
    ◼ メンバをpublicにしたくない
    ◼ でもリフレクションでアクセスさせたい
    #javajo
    92/137

    View Slide

  93. opens命令
    opens命令でパッケージを指定することで、
    外部からリフレクションができるようになる
    module net.example.ace_shooter {
    opens net.example.ace_shooter.core;
    ...
    }
    #javajo
    93/137

    View Slide

  94. openモジュール
    モジュール宣言にopenを修飾すると、
    すべてのパッケージがopens指定される
    open module net.example.ace_shooter {
    ...
    }
    #javajo
    94/137

    View Slide

  95. リフレクション
    リフレクションは
    もはや魔法の杖ではない!
    #javajo
    95/137

    View Slide

  96. コンパイルと実行
    #javajo
    96/137

    View Slide

  97. コンパイルと実行
    注意点:
    ◼ プログラムのコンパイル方法、実行時の
    プログラム配置方法はJava SE実装依存
    ◼ 本セッションは、Java SEの参照実装で
    あるOpenJDKを前提とする
    #javajo
    97/137

    View Slide

  98. モジュールパス
    モジュールパス:
    ◼ モジュールのJARファイルを配置する
    パス
    ◼ クラスパスとは別!
    #javajo
    98/137

    View Slide

  99. コンパイル
    javacコマンドの主なオプション
    オプション 内容
    --module-path ¥
    {モ ジ ュ ー ル パス}
    依存先モジュールの配置場所
    --module-source-path ¥
    {モジュールソースパス}
    複数モジュールを同時コンパイル
    する時、モジュールのソースディ
    レクトリの配置場所
    ※あまり使わないはず
    --module-version ¥
    {バ ー ジ ョン}
    モジュールのバージョン
    ※いまのところ使い道は無い
    #javajo
    99/137

    View Slide

  100. ブートレイヤー
    実行
    初期モジュール(mainを含むモジュール)か
    ら推移的に参照されるモジュール、および
    SPIの実装を提供するモジュールが
    ブートレイヤー(実行時の構成)に含まれる
    module Main
    java.base
    java.desktop
    java.sql
    module X
    module Y
    module Z
    モ ジ ュ ー ル パ ス
    #javajo
    100/137

    View Slide

  101. 実行
    javaコマンドの主なオプション
    オプション 内 容
    --module-path ¥
    {モ ジ ュ ー ル パス}
    モ ジ ュ ー ル の 場 所
    --module ¥
    {初 期 モ ジ ュ ー ル名}/{メインクラス }
    mainメソッドを持つ
    ク ラ ス
    --module {初期モジュール 名} 初 期 モ ジ ュ ー ル
    --add-modules ¥
    {モ ジ ュ ー ル名},{モジュール名},...
    指定したモジュール
    を ブ ー ト レ イ ヤ ー に
    追 加
    #javajo
    101/137

    View Slide

  102. 経過措置
    #javajo
    102/137

    View Slide

  103. 経過措置
    ⚫ 現時点で、多くのプログラムのJARは、
    module-info.classを含んでいない
    ⚫ モジュールの世界への経過措置として、
    二種類の特殊なモジュールが導入された
    ◼ 無名モジュール
    ◼ 自動モジュール
    #javajo
    103/137

    View Slide

  104. 無名モジュール
    ⚫ クラスパス上のクラスファイルは、
    無名モジュールの中でロードされる
    ⚫ 無名モジュールは:
    ◼ モジュール名を持たない
    ◼ すべてのモジュールをrequiresする
    ◼ すべてのパッケージをexportsする
    ◼ (Java SE実装依存)外部モジュールの
    非公開メンバへのリフレクションが可能
    #javajo

    104/137

    View Slide

  105. 自動モジュール
    ⚫ モジュールパス上のJARファイルのうち、
    module-info.classを持たないものは、
    自動モジュールとしてロードされる
    ⚫ 自動モジュールは:
    ◼ モジュールパス上の
    すべてのモジュールをrequiresする
    ◼ すべての無名モジュールをrequiresする
    ◼ すべてのパッケージをexportsする
    ◼ すべてのパッケージをopensする
    #javajo
    105/137

    View Slide

  106. 自動モジュール
    自動モジュールのモジュール名の決定方法:
    1. JARのMANIFEST.MFファイルが
    Automatic-Module-Name属性を持って
    いる場合、その値がモジュール名
    2. そうでない場合、JARファイル名を元に
    モジュール名が作られる
    ◆ commons-io.jar
    → commons_ioモジュール
    #javajo
    106/137

    View Slide

  107. モジュール世界への移行
    #javajo
    107/137

    View Slide

  108. モジュール世界への移行
    ソフトウェア種別ごとのモジュール化指針:
    種別 モジュール化指針
    ライブラリ いますぐモジュール化!
    プラグイン 基盤ミドルウェア次第
    APサーバ上の
    アプリケーション
    基盤ミドルウェア次第
    ※Java EE 8はモジュール非対応
    スタンドアロンの
    アプリケーション
    遅くなりすぎない程度に
    モジュール化する場合もしない場合も、
    JDK9への移行ガイドは必読
    #javajo
    108/137

    View Slide

  109. ライブラリのモジュール化
    ライブラリのモジュール化が喫緊な理由:
    ◼ ライブラリを使う側のプログラムが、
    requires命令を書けるようにするため
    #javajo
    109/137

    View Slide

  110. ライブラリのモジュール化
    JARファイル名ベースの自動モジュールを
    requiresしてはいけない!
    module org.example.matrix {
    requires commons_io;
    ...
    }

    駄目パターン:
    → Commons IOに本当のモジュール名が
    付いたとき、ライブラリを使う側のプログラムが
    不整合になる
    ※ requires staticは許容範囲
    #javajo
    110/137

    View Slide

  111. ライブラリのモジュール化
    モジュール化のフロー
    すべてのrequires先JARの
    モジュール名が決まるまで待つ
    Automatic-Module-Nameで
    モジュール名を決めて公開
    module-info.javaを書いて公開
    すべての requires先JAR の
    モジュール名が決まっている?
    No
    Yes
    #javajo
    111/137

    View Slide

  112. ライブラリのモジュール化
    Java SE 8以前をサポートしたい時:
    ◼ Automatic-Module-Name属性を付ける
    → これは簡単
    ◼ module-info.javaが書きたい場合、
    module-info.javaだけをJava SE 9用に
    コンパイルする
    #javajo
    112/137

    View Slide

  113. モジュールのテスト
    #javajo
    113/137

    View Slide

  114. モジュールのテスト
    二種類のテスト
    ブ ラ ッ ク ボ ッ ク ス
    ・テスト
    ⚫ モ ジ ュ ー ル の 外 か ら テ スト 。
    ⚫ exportsされたパッケージの、public な
    ク ラ ス を 操 作 し て 、 仕 様ど お りに 動 く
    こ と を 確 か め る 。
    ⚫ テ ス ト コ ー ド は 、 テ ス ト対 象 と
    別 モ ジ ュ ー ル 。
    ホ ワ イ ト ボ ッ ク ス
    ・テスト
    ⚫ モ ジ ュ ー ル の 内 側 を テ スト 。
    ⚫ 公 開・非公開にかかわらず、クラ ス・
    メソッドを操作して、意図した実装に
    な っ て い る こ と を 確 か める 。
    ⚫ テ ス ト コ ー ド は 、 テ ス ト対 象 と
    同 一 モ ジ ュ ー ル……どうやって?
    #javajo
    114/137

    View Slide

  115. ホワイトボックス・テスト
    ホワイトボックス・テストの課題:
    ◼ テストコードは、JUnit, TestNG, JMockit
    など、テスト用ライブラリを使う
    ◆ テスト対象コードは、これらのライブ
    ラリをrequiresしていない
    ◼ コンパイル済みのモジュールに、テスト
    コードのクラスを追加する必要がある
    #javajo
    115/137

    View Slide

  116. ホワイトボックス・テスト
    ふたつのやり方:
    正攻法 → こちらを解説
    ⚫ テスト対象のモジュール定義を、
    テストできる構成に一時的に上書き
    ⚫ javac/javaコマンドにオプションを指定
    次善の策
    ⚫ あきらめてクラスパス上でテスト
    #javajo
    116/137

    View Slide

  117. モジュール定義の上書き
    JDKのjavac/javaコマンド共通オプション
    オプション 内 容
    --add-reads ¥
    {モ ジ ュ ー ル名}={参照先モジュール},...
    requires定義を追加
    --patch-module ¥
    {モ ジ ュ ー ル名}={ファイル,...},...
    モ ジ ュ ー ル に ソ ー
    ス フ ァ イ ル/クラス
    フ ァ イ ル を 追 加
    #javajo
    117/137

    View Slide

  118. モジュール定義の上書き
    javac ... ¥
    --add-reads app=junit ¥
    --patch-module app=ATest.java,BTest.java
    java ... ¥
    --add-reads app=junit ¥
    --patch-module app=ATest.class,BTest.class ¥
    --add-modules ALL-MODULE-PATH
    コンパイル
    実行
    モ ジ ュ ー ル パ ス 上 の 全JARを実行構成に含める
    #javajo
    118/137

    View Slide

  119. jlink
    #javajo
    119/137

    View Slide

  120. #javajo
    jlink
    jlink
    ◼ 必要なモジュールだけを含んだカスタム
    のJava処理系を生成するツール
    ◼ jlinkコマンドとしてJDKに付属する
    ◼ 対応するJSRは無い
    120/137

    View Slide

  121. #javajo
    jlink登場の背景
    ⚫ コンテナに同梱するJava処理系は、サイズ
    を小さくしたい
    ⚫ 「どこにでもJavaが入っている」ことは、
    もはや期待できない。Javaプログラムを配
    る際には、Java処理系自体の配布も合わせ
    て設計する必要がある
    121/137

    View Slide

  122. 基本的な使い方
    #javajo
    jlink --module-path build/jars ¥
    --add-modules jp.example.hoge,org.slf4j.simple ¥
    --launcher cmd=jp.example.hoge/jp.example.hoge.main.Main ¥
    --output build/pkg
    build/pkg: カスタムJava処理系
    build/pkg/lib: モジュール、ネイティブライブラリ等
    build/pkg/bin: コマンド
    122/137

    View Slide

  123. 主なコマンドラインオプション
    #javajo
    オプション 内容
    --module-path {モ ジ ュ ー ル パ ス} モジュールを探す場所
    --add-modules ¥
    {モ ジ ュ ー ル1},{モジュール2},...
    処理系に追加する
    モジュールの起点
    --bind-services
    SPIの実装を提供するモ
    ジュールも処理系に含む
    --launcher { コ マ ン ド 名 }={初期
    モジュール }/{メインクラス}
    mainメソッドを持つクラ

    --launcher { コ マ ン ド 名 }={初期
    モジュール }
    初期モジュール
    --output {出力先ディレクトリ} 処理系の出力先
    123/137

    View Slide

  124. #javajo
    処理系に含まれるモジュール
    次のモジュールが処理系に含まれる
    ◼ --add-modulesオプションで指定した
    モジュール
    ◼ 処理系に含まれるモジュールから
    requiresされるモジュール
    ◼ 処理系に含まれるモジュールがusesする
    サービスの実装をprovidesする
    モジュール(→次章)
    124/137

    View Slide

  125. #javajo
    プラットフォームに関する注意
    ⚫ 生成されるJava処理系は、
    プラットフォーム固有のもの
    ⚫ Windows用のJava処理系を生成するには、
    Windows上でjlinkを実行する必要がある
    125/137

    View Slide

  126. #javajo
    ライセンスに関する注意
    ⚫ OTNライセンスにもとづいてjlinkを実行し
    た場合、生成されるJava処理系にもOTNラ
    イセンスが(おそらく)適用される
    ◼ この場合、生成されるJava処理系を本番
    用途で使うことは(おそらく)できない
    ⚫ カスタム処理系をひっくるめて納品する
    場合、処理系自体のライセンスに抵触しな
    いようにする必要がある
    126/137

    View Slide

  127. 高度なトピック
    #javajo
    127/137

    View Slide

  128. ServiceLoader/SPI
    ServiceLoader/SPIの仕組みは
    モジュール・システムに統合された
    ◼ サービスを使うモジュールは、
    uses命令でサービスのインタフェースを
    指定
    ◼ サービスを提供するモジュールは、
    provides命令でサービスの実装を指定
    #javajo
    128/137

    View Slide

  129. requires static
    コンパイル時に必要だが、実行時には不要な
    モジュールがrequires static命令で指定できる
    ◼ 例: JSR 305の@Nullableアノテーション
    #javajo
    129/137

    View Slide

  130. ブートレイヤー
    モジュールレイヤー
    モジュールレイヤー: モジュールの名前空間
    java.base
    java.sql
    jp.example.app_container
    java.desktop
    java.logging
    アプリ X のレイヤー アプリ Yのレイヤー
    com.example.app_x org.example.app_y
    net.example.utils net.example.utils




    アプリケーションサーバや、プラグイン機構の
    基礎となる仕組み
    #javajo
    130/137

    View Slide

  131. モジュールレイヤー
    クラスローダーとモジュールレイヤーの関連
    Module ModuleLayer
    ClassLoader
    Class
    Package
    Unnamed
    Module
    Named
    Module
    http://d.hatena.ne.jp/miyakawa_taku/20171108/1510145001
    #javajo
    131/137

    View Slide

  132. OSGiとの違い
    ⚫ OSGiはロード・関連付けするミドルウェア
    を仕様に含むが、
    Javaのモジュール・システムは含まない
    ⚫ Javaのモジュール・システムは、OSGiの
    ようなものを作るための基礎と考えられる
    #javajo
    132/137

    View Slide

  133. モジュール・システムの
    参考資料
    #javajo
    133/137

    View Slide

  134. モジュール・システムの参考資料
    Bakker, Mak (2017)『Java 9 Modularity』
    #javajo
    134/137

    View Slide

  135. 註釈
    #javajo
    135/137

    View Slide

  136. † パッケージの衝突検知
    「複数のモジュールが同一パッケージを含む場
    合、起動時に検知される」
    ◼ 厳密には、「モジュールレイヤーが、モ
    ジュール間のパッケージ重複を許さない構
    成である時、そのモジュールレイヤー内の
    複数のモジュールが~」である
    ◼ 異なるモジュールレイヤー間では、同じ名
    前のパッケージが共存できる
    ◼ defineModulesWithManyLoadersで作られた
    モジュールレイヤーは、exportされない
    パッケージの重複を許す
    #javajo
    136/137

    View Slide

  137. ‡ 強固なカプセル化の緩和
    「(Java SE実装依存)外部モジュールの非公
    開メンバへのリフレクションが可能」
    ◼ Java SE 9仕様(JSR 379)では、Java
    SE実装が、このような動作をデフォル
    トとしてもよい、と規定されている
    (Relaxing strong encapsulation節)
    #javajo
    137/137

    View Slide