Pro Yearly is on sale from $80 to $50! »

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.

5e8c7a93f4cd63b62ced5dd347f1a8e0?s=128

Miyakawa Taku

December 23, 2018
Tweet

Transcript

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

    BY 4.0 にもとづいて許諾します
  2. ⚫ @miyakawa_taku ⚫ JJUG幹事 ⚫ Salesforceで働いています ⚫ 奄美出身の力士が好きです☆ ⚫ オレオレJVM言語Kinkを作っています

    https://bitbucket.org/kink/kink 自己紹介 #javajo 2/137
  3. 本セッションのあらまし ⚫ Java SE 8からJava SE 11に掛けて、 たくさんのことが起こりました ◼ JDKのリリースモデル変更

    ◼ モジュールシステムの導入 ◼ 各種機能の追加・変更・廃止・切り離し ⚫ 何が起きたのか把握して、 安心して11+に踏み出しましょう☆ ⚫ とはいえ #javajo 3/137
  4. とはいえ ⚫ たいへんな道のりであることは確かです #javajo 4/137

  5. 本セッションの基調低音 ⚫ Javaは変わりつつある ⚫ Write Once Run Anywhereの担い手という 役割は縮小している ⚫

    一方で、サーバサイド処理系としての 進化はペースを上げている #javajo 5/137
  6. 演目 Java SE, JDKってなんだっけ Java SEをとりまく環境の変化 モジュールシステムとjlink #javajo 6/137

  7. スコープ 主に触れること ◼ Java処理系関連のざっくりした傾向 ◼ モジュール関連の機能 触れないこと ◼ 実装固有の機能: GC,

    内部処理改善等 ◼ 外部ツール・ライブラリの対応状況 → Migration Guide from Java 8 to Java 11 by 久保田さん #javajo 7/137
  8. #javajo ハンズオン Linux, macOS用ハンズオン ◼ https://quip.com/axDqAMIbZjnR/Java- 11-Linux-macOS Windows用ハンズオン ◼ https://quip.com/edM1AVI5xssC/Java-

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

  10. Java SEとは Java SE: Java処理系の規格 ◼ 正式名称: Java Standard Edition

    ◼ 規格の中身: ◆ 言語仕様 ◆ Java仮想マシンの仕様 ◆ 標準APIの仕様 ◼ 代表的な実装: OpenJDK, Oracle JDK等 #javajo 10/137
  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
  12. Java SEの規格開発プロセス Java Community Process (JCP) ◼ 正式な規格化プロセス ◼ Expert

    Groupによるドラフト提出、 Executive Committeeの投票を通して、 個々の仕様であるJSRを策定 ◼ Java MEやEEも対象(だった) ◆ Jakarta EEは対象外 ◼ きっちりしたはる #javajo 12/137
  13. Java SEの規格開発プロセス JDK Enhancement Proposal (JEP) ◼ OpenJDKの開発プロセス ◼ 主にML内で合意形成される

    ◼ Python Enhancement Proposalがお手本 ◼ 2011年以降、実質的にはJEPが規格化を 引っ張る ◼ Java SEの規格に入らない、実装固有の 機能(例: GC方式)も議論の対象 #javajo 13/137
  14. Java SE 9, 10, 11 モジュール以外の主な新機能 #javajo 14/137

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

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

  17. List.of List<String> a = Collections.emptyList(); List<String> b = Collections.singletonList("foo"); List<String>

    c = Collections.unmodifiableList(Arrays.asList("foo", "bar")); List<String> a = List.of(); List<String> b = List.of("foo"); List<String> c = List.of("foo", "bar"); ~Java SE 8 Java SE 9~ #javajo 17/137
  18. Map.of Map<String, Integer> m = new HashMap<>(); m.put("双葉山", 69); m.put("大鵬",

    45); m.put("白鵬", 63); Map<String, Integer> yokozuna = Collections.unmodifiableMap(m); ~Java SE 8 Map<String, Integer> yokozuna = Map.of("双葉山", 69, "大鵬", 45, "白鵬", 63); Java SE 9~ #javajo 18/137
  19. Java SE 9: JEP 213 try-with-resourcesの改善 #javajo 19/137

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

  22. ResourceBundle→UTF-8 ~Java SE 8 Java SE 9~ ⚫ ResourceBundleのプロパティファイルは デフォルトでLatin-1

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

  24. var記法 var トリオ漫才 = List.of( "横山ホットブラザーズ", "かしまし娘", "宮川左近ショー"); トリオ漫才.forEach(System.out::println); Java

    SE 10, 11 List<String>トリオ漫才 = List.of( "横山ホットブラザーズ", "かしまし娘", "宮川左近ショー"); トリオ漫才.forEach(System.out::println); Java SE 9 ローカル変数宣言で型が省略できるように #javajo 24/137
  25. Java SE 11: JEP 320 サーバ向け機能の削除 #javajo 25/137

  26. サーバ向け機能の削除 Java SE 11で削除された主なサーバ向け機能: ◼ ドロップインの代替ライブラリあり ◆ JAXBのAPIとデフォルト実装 ◆ JAX-WSのAPI

    ◆ JTAのAPI ◼ ドロップインの代替ライブラリなし ◆ CORBA → 該当機能を使用中の場合、移行時に要対応 #javajo 26/137
  27. Java SE 11 デスクトップ向け機能の削除 #javajo 27/137

  28. デスクトップ向け機能の削除 Java SE 11でApplet*が削除 ◼ 主要ブラウザはNPAPI廃止済みのため、 既に使えなくなっていた ◼ ブラウザプラグイン自体が下火 Flash,

    Silverlightも廃止予定 ◼ HTML5時代の必然 #javajo * Applet: ブラウザプラグイン上で動く Java プログラム。 Flashみたいな感じ 28/137
  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
  30. どうなるJavaデスクトップ? ⚫ Javaデスクトップ環境にとっては 大きな転換点 ◼ 参考: https://aoe-tk.hatenablog.com/en try/2018/03/11/203708 ⚫ 転換には、Public

    JREの廃止が密接に関連 → 次章! #javajo 30/137
  31. 演目 Java SE, JDKってなんだっけ Java SEをとりまく環境の変化 モジュールシステムとjlink #javajo 31/137

  32. Java SEをとりまく環境の変化 Java SE 8から11にかけての大変動: ◼ OpenJDK, Oracle JDKの リリースサイクル変更(Java

    9~) ◼ Oracle JDKのライセンス変更 (Java 11~) ◼ Public JRE配布の廃止 (Java 11~) ◼ OpenJDKエコシステムの活発化 #javajo 32/137
  33. OpenJDK, Oracle JDKの リリースサイクル変更 #javajo 33/137

  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
  35. 私見 時間で切ってリズムを作ることの有益さは 実証されている ◼ Scrum ◼ Ubuntu ◼ JJUGも! 開発の観点でのメリットは大きい

    望むらくはエコシステム全体にとっても #javajo 35/137
  36. Oracle JDKのライセンス変更 #javajo 36/137

  37. Oracle JDKのライセンス変更 ~Java 10 ◼ 公開で配布されるOracle JDKは、 BCLのもとに利用が許諾された ◆ 開発・本番運用ともに利用OK

    ◆ リバースエンジニアリングはダメ #javajo 37/137
  38. Oracle JDKのライセンス変更 Java 11~ ◼ OTNライセンスに変更 ◆ 開発用途の利用はOK ◆ 本番用途はダメ

    ◼ 本番用途でOracle JDKを使うには、 サブスクリプションの契約が必要 ※ 3年ごとのLTS版(11, 17, ...)に、 半年を超えてパッチが提供される #javajo 38/137
  39. かわりにOpenJDKを使えば良い? ⚫ もちろん! ⚫ OpenJDKのライセンスはGPLv2+CPE つまり自由に利用・改変・再配布できる ⚫ Oracle JDKと中身はほとんど同じ ⚫

    ただし、本家サイトでのバイナリ配布は ◼ x86-64版のみ ◼ zip/tar.gzアーカイブのみ #javajo 39/137
  40. Public JRE配布の廃止 #javajo 40/137

  41. WORA! ⚫ Javaのプログラムはどこでも動く Write Once, Run Anywhere! ⚫ OSがUnixでもWindowsでも ⚫

    CPUがx86でもSparcでもARMでも ⚫ ただし、Javaがインストールされていれば #javajo 41/137
  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
  43. 時代の終わり ⚫ 「どこでもJavaが入っている」時代は 終わった ◼ iPhone登場時点で終わっていたのかも ◼ 今はむしろ、ブラウザとJavaScriptが WORAの担い手 #javajo

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

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

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

    #javajo 46/137
  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
  48. 開発の加速 加速するOpenJDK開発 ◼ たくさんの新GC方式 ◆ G1GC, ZGC, Shenandoah ◼ 起動時間の改善

    ◆ Class Data Sharing, AOT Compilation ◼ フットプリント削減: jlink ◼ 新JITコンパイラ: Graal ◼ 新仕様群: Panama, Vallhara, Loom, ... #javajo 48/137
  49. OpenJDKディストロ 素のOpenJDKを使うのはハードルが高い ◼ バイナリ提供: x86-64版のみ ◼ パッケージング: zip/tar.gzアーカイブ → 各種OpenJDKディストリビューションに

    注目が集まる #javajo 49/137
  50. OpenJDKディストロ ⚫ AdoptOpenJDK ⚫ Red Hat OpenJDK ⚫ Azul Zulu

    ⚫ Amazon Corretto #javajo 50/137
  51. #javajo AdoptOpenJDK ⚫ AdoptOpenJDK ⚫ 様々なプラットフォーム向けに OpenJDKをビルド・テストして提供する、 コミュニティベースのプロジェクト ⚫ Windows

    (x86, x86-64), Mac, Linux (x86-64, Power, ARM64) ⚫ LTS版は最短4年アップデートを提供 51/137
  52. #javajo Red Hat OpenJDK ⚫ Red HatによるOpenJDKパッケージ ⚫ GC実装としてShenandoahが含まれる ⚫

    Red Hat Enterprise Linux, Windows ⚫ 提供バージョンを最短6年アップデート ⚫ 商用サポートあり 52/137
  53. #javajo Azul Zulu ⚫ Zulu ⚫ Java処理系専業企業であるAzul Systemsが 提供するディストロ ⚫

    Windows (x86-64), Mac, Linux (x86-64, ARM64) ⚫ LTS版について8年アップデート ⚫ 商用サポートあり 53/137
  54. #javajo Amazon Corretto ⚫ Amazon Corretto ⚫ Amazon Linuxにバンドルしていた OpenJDKをパッケージ化したもの

    ⚫ Windows (x86, x86-64), Mac, Linux (x86-64) ⚫ 2018年12月時点でOpenJDK 11は未提供 54/137
  55. 注意! Ubuntu公式パッケージ ⚫ Ubuntu 18.04 のopenjdk-ltsパッケージは OpenJDK 10にセキュリティパッチを適用 したもの (2018年12月時点)

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

  57. #javajo Q. 結局なにを使えば良いの? A. 場合による 要件として検討するべき項目: ◼ Javaを動かすプラットフォームは? ◼ 何年後にメジャーアップデートする?

    ◼ パッチ適用の頻度・機会・方式は? ◼ 商用サポートは必要? ◼ …… 57/137
  58. Javaをとりまく環境の変化 小まとめ #javajo 58/137

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

    ⚫ 使う側も実用的で先鋭的になる必要がある 59/137
  60. 演目 Java SE, JDKってなんだっけ Java SEをとりまく環境の変化 モジュールシステムとjlink #javajo 60/137

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

  62. モジュール・システム 内容: ◼ モジュール・システム導入の背景 ◼ モジュール・システムの基本 ◼ リフレクション ◼ コンパイルと実行

    ◼ モジュール世界への移行 ◼ モジュールのテスト ◼ jlink ◼ 高度なトピック #javajo 62/137
  63. モジュール・システム 導入の背景 #javajo 63/137

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

  65. JAR地獄 #javajo 65/137

  66. ~Java 8: JAR地獄 ⚫ JAR地獄 := 大量のJARがクラスパスに 展開されて、混沌にブチ込まれること ◼ 「このJARいらないんじゃない?」

    ◼ → 消したら実行時エラー ⚫ Maven, Gradleのような依存性管理 ツールを使えば少しはマシだけど…… #javajo 66/137
  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
  68. 内部向けパッケージ #javajo 68/137

  69. ~Java 8: 内部向けパッケージ ⚫ プラットフォームやライブラリ内で、 「内部向け」パッケージを作ることがある ◼ org.kink_lang.kink.internal.xxx ◼ sun.misc

    (JDK内) ⚫ 内部向けパッケージは本来、ライブラリ外 からの使用を想定していない ⚫ が、しかし #javajo 69/137
  70. ~Java 8: 内部向けパッケージ GitHubで“import sun.misc.Unsafe”を検索 #javajo 70/137

  71. ~Java 8: 内部向けパッケージ #javajo 71/137

  72. ~Java 8: 内部向けパッケージ ⚫ 内部使用向けのはずのUnsafeクラスが広く 使われてしまっている ◼ 性能を絞り出すため…… ⚫ なにが問題か?

    ◼ 移植性の低いプログラムの蔓延 ◼ 既存のプログラムを壊さないように配慮 すると、実装の改善がしづらい #javajo 72/137
  73. Java処理系の肥大化 #javajo 73/137

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

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

    デプロイが苦しい 75/137
  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
  77. #javajo ~Java 8: Java処理系の肥大化 アプリが使う機能はJava処理系のごく一部 ◼ サーバサイドアプリにSwingは不要 ◼ 制御系組込みシステム以外でCORBAが 使われることはまれ

    使わない機能がフットプリントの大部分を 占めることはやるせない 77/137
  78. モジュール・システムの基本 #javajo 78/137

  79. モジュール・システム ⚫ JARを名前付きのモジュールとして、 カプセル化された配置の単位に ⚫ JAR地獄 → モジュール単位で依存関係を整理 ⚫ 内部向けパッケージ

    → 外部からの使用を実質的に制限 ⚫ Java処理系の肥大化 → jlinkでカスタムのJava処理系を作成 #javajo 79/137
  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
  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
  82. module-info.java モジュール名はソースディレクトリのトップ レベルのmodule-info.javaで宣言 module org.example.matrix { } JARファイルのトップレベルの module-info.class コンパイル

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

    モジュールの外部仕様 の一部とみなせる #javajo 83/137
  84. 使うモジュールの指定 module jp.example.physics { requires org.example.matrix; } モジュールは、自分が使うモジュールを、 requires命令で指定する モジュールが使えるクラスの条件:

    ⚫ requiresした先のモジュールの ⚫ exportsされたパッケージの ⚫ publicなクラス → 該当しないクラスを使うと コンパイルエラー / 実行時例外 #javajo 84/137
  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
  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
  87. exports / requires module A { requires B; } module

    B { exports B.api; requires C; } requiresしたモジュールが存在しないと コンパイルエラー / 実行時例外 #javajo 87/137
  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
  89. リフレクション #javajo 89/137

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

    ◼ 非公開なメンバへのアクセスは、 外部モジュールからは通常不可能 #javajo 90/137
  91. リフレクション 困る例: DI先のクラス package net.example.ace_shooter.engine; public class GameEngine { @Inject

    private PerfMonitor perfMonitor; ... } public にしたくない exportsしたくない リフレクションで触ってほしいクラスは 必ずしも公開したいわけではない #javajo 91/137
  92. リフレクション 必要な緩和策: ◼ パッケージをexportsしたくない ◼ メンバをpublicにしたくない ◼ でもリフレクションでアクセスさせたい #javajo 92/137

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

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

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

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

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

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

  99. コンパイル javacコマンドの主なオプション オプション 内容 --module-path ¥ {モ ジ ュ ー

    ル パス} 依存先モジュールの配置場所 --module-source-path ¥ {モジュールソースパス} 複数モジュールを同時コンパイル する時、モジュールのソースディ レクトリの配置場所 ※あまり使わないはず --module-version ¥ {バ ー ジ ョン} モジュールのバージョン ※いまのところ使い道は無い #javajo 99/137
  100. ブートレイヤー 実行 初期モジュール(mainを含むモジュール)か ら推移的に参照されるモジュール、および SPIの実装を提供するモジュールが ブートレイヤー(実行時の構成)に含まれる module Main java.base java.desktop

    java.sql module X module Y module Z モ ジ ュ ー ル パ ス #javajo 100/137
  101. 実行 javaコマンドの主なオプション オプション 内 容 --module-path ¥ {モ ジ ュ

    ー ル パス} モ ジ ュ ー ル の 場 所 --module ¥ {初 期 モ ジ ュ ー ル名}/{メインクラス } mainメソッドを持つ ク ラ ス --module {初期モジュール 名} 初 期 モ ジ ュ ー ル --add-modules ¥ {モ ジ ュ ー ル名},{モジュール名},... 指定したモジュール を ブ ー ト レ イ ヤ ー に 追 加 #javajo 101/137
  102. 経過措置 #javajo 102/137

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

    自動モジュール #javajo 103/137
  104. 無名モジュール ⚫ クラスパス上のクラスファイルは、 無名モジュールの中でロードされる ⚫ 無名モジュールは: ◼ モジュール名を持たない ◼ すべてのモジュールをrequiresする

    ◼ すべてのパッケージをexportsする ◼ (Java SE実装依存)外部モジュールの 非公開メンバへのリフレクションが可能 #javajo ‡ 104/137
  105. 自動モジュール ⚫ モジュールパス上のJARファイルのうち、 module-info.classを持たないものは、 自動モジュールとしてロードされる ⚫ 自動モジュールは: ◼ モジュールパス上の すべてのモジュールをrequiresする

    ◼ すべての無名モジュールをrequiresする ◼ すべてのパッケージをexportsする ◼ すべてのパッケージをopensする #javajo 105/137
  106. 自動モジュール 自動モジュールのモジュール名の決定方法: 1. JARのMANIFEST.MFファイルが Automatic-Module-Name属性を持って いる場合、その値がモジュール名 2. そうでない場合、JARファイル名を元に モジュール名が作られる ◆

    commons-io.jar → commons_ioモジュール #javajo 106/137
  107. モジュール世界への移行 #javajo 107/137

  108. モジュール世界への移行 ソフトウェア種別ごとのモジュール化指針: 種別 モジュール化指針 ライブラリ いますぐモジュール化! プラグイン 基盤ミドルウェア次第 APサーバ上の アプリケーション

    基盤ミドルウェア次第 ※Java EE 8はモジュール非対応 スタンドアロンの アプリケーション 遅くなりすぎない程度に モジュール化する場合もしない場合も、 JDK9への移行ガイドは必読 #javajo 108/137
  109. ライブラリのモジュール化 ライブラリのモジュール化が喫緊な理由: ◼ ライブラリを使う側のプログラムが、 requires命令を書けるようにするため #javajo 109/137

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

    駄目パターン: → Commons IOに本当のモジュール名が 付いたとき、ライブラリを使う側のプログラムが 不整合になる ※ requires staticは許容範囲 #javajo 110/137
  111. ライブラリのモジュール化 モジュール化のフロー すべてのrequires先JARの モジュール名が決まるまで待つ Automatic-Module-Nameで モジュール名を決めて公開 module-info.javaを書いて公開 すべての requires先JAR の

    モジュール名が決まっている? No Yes #javajo 111/137
  112. ライブラリのモジュール化 Java SE 8以前をサポートしたい時: ◼ Automatic-Module-Name属性を付ける → これは簡単 ◼ module-info.javaが書きたい場合、

    module-info.javaだけをJava SE 9用に コンパイルする #javajo 112/137
  113. モジュールのテスト #javajo 113/137

  114. モジュールのテスト 二種類のテスト ブ ラ ッ ク ボ ッ ク ス

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

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

    次善の策 ⚫ あきらめてクラスパス上でテスト #javajo 116/137
  117. モジュール定義の上書き JDKのjavac/javaコマンド共通オプション オプション 内 容 --add-reads ¥ {モ ジ ュ

    ー ル名}={参照先モジュール},... requires定義を追加 --patch-module ¥ {モ ジ ュ ー ル名}={ファイル,...},... モ ジ ュ ー ル に ソ ー ス フ ァ イ ル/クラス フ ァ イ ル を 追 加 #javajo 117/137
  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
  119. jlink #javajo 119/137

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

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

    121/137
  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
  123. 主なコマンドラインオプション #javajo オプション 内容 --module-path {モ ジ ュ ー ル

    パ ス} モジュールを探す場所 --add-modules ¥ {モ ジ ュ ー ル1},{モジュール2},... 処理系に追加する モジュールの起点 --bind-services SPIの実装を提供するモ ジュールも処理系に含む --launcher { コ マ ン ド 名 }={初期 モジュール }/{メインクラス} mainメソッドを持つクラ ス --launcher { コ マ ン ド 名 }={初期 モジュール } 初期モジュール --output {出力先ディレクトリ} 処理系の出力先 123/137
  124. #javajo 処理系に含まれるモジュール 次のモジュールが処理系に含まれる ◼ --add-modulesオプションで指定した モジュール ◼ 処理系に含まれるモジュールから requiresされるモジュール ◼

    処理系に含まれるモジュールがusesする サービスの実装をprovidesする モジュール(→次章) 124/137
  125. #javajo プラットフォームに関する注意 ⚫ 生成されるJava処理系は、 プラットフォーム固有のもの ⚫ Windows用のJava処理系を生成するには、 Windows上でjlinkを実行する必要がある 125/137

  126. #javajo ライセンスに関する注意 ⚫ OTNライセンスにもとづいてjlinkを実行し た場合、生成されるJava処理系にもOTNラ イセンスが(おそらく)適用される ◼ この場合、生成されるJava処理系を本番 用途で使うことは(おそらく)できない ⚫

    カスタム処理系をひっくるめて納品する 場合、処理系自体のライセンスに抵触しな いようにする必要がある 126/137
  127. 高度なトピック #javajo 127/137

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

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

    129/137
  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
  131. モジュールレイヤー クラスローダーとモジュールレイヤーの関連 Module ModuleLayer ClassLoader Class Package Unnamed Module Named

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

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

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

  135. 註釈 #javajo 135/137

  136. † パッケージの衝突検知 「複数のモジュールが同一パッケージを含む場 合、起動時に検知される」 ◼ 厳密には、「モジュールレイヤーが、モ ジュール間のパッケージ重複を許さない構 成である時、そのモジュールレイヤー内の 複数のモジュールが~」である ◼

    異なるモジュールレイヤー間では、同じ名 前のパッケージが共存できる ◼ defineModulesWithManyLoadersで作られた モジュールレイヤーは、exportされない パッケージの重複を許す #javajo 136/137
  137. ‡ 強固なカプセル化の緩和 「(Java SE実装依存)外部モジュールの非公 開メンバへのリフレクションが可能」 ◼ Java SE 9仕様(JSR 379)では、Java

    SE実装が、このような動作をデフォル トとしてもよい、と規定されている (Relaxing strong encapsulation節) #javajo 137/137