Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

デスクトップ向け機能の削除 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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

リリースサイクル変更 ~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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

JAR地獄 #javajo 65/137

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

~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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

~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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

パッケージ衝突の検知 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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

標準モジュール 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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

経過措置 #javajo 102/137

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

ライブラリのモジュール化 JARファイル名ベースの自動モジュールを requiresしてはいけない! module org.example.matrix { requires commons_io; ... } 駄目パターン: → Commons IOに本当のモジュール名が 付いたとき、ライブラリを使う側のプログラムが 不整合になる ※ requires staticは許容範囲 #javajo 110/137

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

モジュール定義の上書き 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

Slide 119

Slide 119 text

jlink #javajo 119/137

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

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

Slide 122

Slide 122 text

基本的な使い方 #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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

ブートレイヤー モジュールレイヤー モジュールレイヤー: モジュールの名前空間 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

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

註釈 #javajo 135/137

Slide 136

Slide 136 text

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

Slide 137

Slide 137 text

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