Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Java SE 8から11で何が起きた?一気におさらいしてみよう! /java-se-8-to-11
Search
Miyakawa Taku
December 23, 2018
Programming
15
5k
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
Share
More Decks by Miyakawa Taku
See All by Miyakawa Taku
入門: 末尾呼び出し最適化 /tail-call-elimination-intro
miyakawataku
2
2.2k
JVM言語の動き方・動かし方 /make-jvm-lang
miyakawataku
6
2k
ミニバッチサイズと学習率の関係 /small-batch-learning
miyakawataku
0
2k
機械学習プロジェクトの進め方 /howtoproceedwithmlproject
miyakawataku
0
330
グラフアルゴリズムその2: 単一始点最短路問題 /graphShortestPaths
miyakawataku
0
150
Strassenのアルゴリズムによる行列積の計算 /strassen-algorithm
miyakawataku
8
3.1k
Viterbiのアルゴリズム /viterbi-algorithm
miyakawataku
0
250
Other Decks in Programming
See All in Programming
From Translations to Multi Dimension Entities
alexanderschranz
2
130
PHPUnitしか使ってこなかった 一般PHPerがPestに乗り換えた実録
mashirou1234
0
180
103 Early Hints
sugi_0000
1
230
Zoneless Testing
rainerhahnekamp
0
120
Beyond ORM
77web
5
660
Cloudflare MCP ServerでClaude Desktop からWeb APIを構築
kutakutat
1
540
rails stats で紐解く ANDPAD のイマを支える技術たち
andpad
1
290
採用事例の少ないSvelteを選んだ理由と それを正解にするためにやっていること
oekazuma
2
1k
生成AIでGitHubソースコード取得して仕様書を作成
shukob
0
360
nekko cloudにおけるProxmox VE利用事例
irumaru
3
430
[JAWS-UG横浜 #76] イケてるアップデートを宇宙いち早く紹介するよ!
maroon1st
0
460
ブラウザ単体でmp4書き出すまで - muddy-web - 2024-12
yue4u
3
470
Featured
See All Featured
Building Flexible Design Systems
yeseniaperezcruz
327
38k
Building a Scalable Design System with Sketch
lauravandoore
460
33k
Fireside Chat
paigeccino
34
3.1k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.3k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
44
9.3k
Bash Introduction
62gerente
608
210k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
Building Adaptive Systems
keathley
38
2.3k
Transcript
Java SE 8から11で何が起きた? 一気におさらいしてみよう! 2018-12-23 Java女子部 #javajo 宮川 拓 本文書の利用をCC
BY 4.0 にもとづいて許諾します
⚫ @miyakawa_taku ⚫ JJUG幹事 ⚫ Salesforceで働いています ⚫ 奄美出身の力士が好きです☆ ⚫ オレオレJVM言語Kinkを作っています
https://bitbucket.org/kink/kink 自己紹介 #javajo 2/137
本セッションのあらまし ⚫ Java SE 8からJava SE 11に掛けて、 たくさんのことが起こりました ◼ JDKのリリースモデル変更
◼ モジュールシステムの導入 ◼ 各種機能の追加・変更・廃止・切り離し ⚫ 何が起きたのか把握して、 安心して11+に踏み出しましょう☆ ⚫ とはいえ #javajo 3/137
とはいえ ⚫ たいへんな道のりであることは確かです #javajo 4/137
本セッションの基調低音 ⚫ Javaは変わりつつある ⚫ Write Once Run Anywhereの担い手という 役割は縮小している ⚫
一方で、サーバサイド処理系としての 進化はペースを上げている #javajo 5/137
演目 Java SE, JDKってなんだっけ Java SEをとりまく環境の変化 モジュールシステムとjlink #javajo 6/137
スコープ 主に触れること ◼ Java処理系関連のざっくりした傾向 ◼ モジュール関連の機能 触れないこと ◼ 実装固有の機能: GC,
内部処理改善等 ◼ 外部ツール・ライブラリの対応状況 → Migration Guide from Java 8 to Java 11 by 久保田さん #javajo 7/137
#javajo ハンズオン Linux, macOS用ハンズオン ◼ https://quip.com/axDqAMIbZjnR/Java- 11-Linux-macOS Windows用ハンズオン ◼ https://quip.com/edM1AVI5xssC/Java-
11-Windows 8/137
演目 Java SE, JDKってなんだっけ Java SEをとりまく環境の変化 モジュールシステムとjlink #javajo 9/137
Java SEとは Java SE: Java処理系の規格 ◼ 正式名称: Java Standard Edition
◼ 規格の中身: ◆ 言語仕様 ◆ Java仮想マシンの仕様 ◆ 標準APIの仕様 ◼ 代表的な実装: OpenJDK, Oracle JDK等 #javajo 10/137
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
Java SEの規格開発プロセス Java Community Process (JCP) ◼ 正式な規格化プロセス ◼ Expert
Groupによるドラフト提出、 Executive Committeeの投票を通して、 個々の仕様であるJSRを策定 ◼ Java MEやEEも対象(だった) ◆ Jakarta EEは対象外 ◼ きっちりしたはる #javajo 12/137
Java SEの規格開発プロセス JDK Enhancement Proposal (JEP) ◼ OpenJDKの開発プロセス ◼ 主にML内で合意形成される
◼ Python Enhancement Proposalがお手本 ◼ 2011年以降、実質的にはJEPが規格化を 引っ張る ◼ Java SEの規格に入らない、実装固有の 機能(例: GC方式)も議論の対象 #javajo 13/137
Java SE 9, 10, 11 モジュール以外の主な新機能 #javajo 14/137
Java SE 9: JEP 269 コレクションのファクトリ #javajo 15/137
コレクションのファクトリ List.of, Set.of, Map.ofメソッドで、不変な コレクションが作れるようになりました☆ #javajo 16/137
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
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
Java SE 9: JEP 213 try-with-resourcesの改善 #javajo 19/137
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
Java SE 9: JEP 226 ResourceBundleプロパティが デフォルトUTF-8に☆ #javajo 21/137
ResourceBundle→UTF-8 ~Java SE 8 Java SE 9~ ⚫ ResourceBundleのプロパティファイルは デフォルトでLatin-1
⚫ 日本語などのメッセージはnative2asciiで エスケープする必要があった ⚫ ResourceBundleのプロパティファイルが デフォルトでUTF-8に☆ ⚫ 注意: Propertiesクラスのデフォルトは Latin-1のまま #javajo 22/137
Java SE 10, 11: JEP 286, 323 var記法 #javajo 23/137
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
Java SE 11: JEP 320 サーバ向け機能の削除 #javajo 25/137
サーバ向け機能の削除 Java SE 11で削除された主なサーバ向け機能: ◼ ドロップインの代替ライブラリあり ◆ JAXBのAPIとデフォルト実装 ◆ JAX-WSのAPI
◆ JTAのAPI ◼ ドロップインの代替ライブラリなし ◆ CORBA → 該当機能を使用中の場合、移行時に要対応 #javajo 26/137
Java SE 11 デスクトップ向け機能の削除 #javajo 27/137
デスクトップ向け機能の削除 Java SE 11でApplet*が削除 ◼ 主要ブラウザはNPAPI廃止済みのため、 既に使えなくなっていた ◼ ブラウザプラグイン自体が下火 Flash,
Silverlightも廃止予定 ◼ HTML5時代の必然 #javajo * Applet: ブラウザプラグイン上で動く Java プログラム。 Flashみたいな感じ 28/137
デスクトップ向け機能の削除 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
どうなるJavaデスクトップ? ⚫ Javaデスクトップ環境にとっては 大きな転換点 ◼ 参考: https://aoe-tk.hatenablog.com/en try/2018/03/11/203708 ⚫ 転換には、Public
JREの廃止が密接に関連 → 次章! #javajo 30/137
演目 Java SE, JDKってなんだっけ Java SEをとりまく環境の変化 モジュールシステムとjlink #javajo 31/137
Java SEをとりまく環境の変化 Java SE 8から11にかけての大変動: ◼ OpenJDK, Oracle JDKの リリースサイクル変更(Java
9~) ◼ Oracle JDKのライセンス変更 (Java 11~) ◼ Public JRE配布の廃止 (Java 11~) ◼ OpenJDKエコシステムの活発化 #javajo 32/137
OpenJDK, Oracle JDKの リリースサイクル変更 #javajo 33/137
リリースサイクル変更 ~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
私見 時間で切ってリズムを作ることの有益さは 実証されている ◼ Scrum ◼ Ubuntu ◼ JJUGも! 開発の観点でのメリットは大きい
望むらくはエコシステム全体にとっても #javajo 35/137
Oracle JDKのライセンス変更 #javajo 36/137
Oracle JDKのライセンス変更 ~Java 10 ◼ 公開で配布されるOracle JDKは、 BCLのもとに利用が許諾された ◆ 開発・本番運用ともに利用OK
◆ リバースエンジニアリングはダメ #javajo 37/137
Oracle JDKのライセンス変更 Java 11~ ◼ OTNライセンスに変更 ◆ 開発用途の利用はOK ◆ 本番用途はダメ
◼ 本番用途でOracle JDKを使うには、 サブスクリプションの契約が必要 ※ 3年ごとのLTS版(11, 17, ...)に、 半年を超えてパッチが提供される #javajo 38/137
かわりにOpenJDKを使えば良い? ⚫ もちろん! ⚫ OpenJDKのライセンスはGPLv2+CPE つまり自由に利用・改変・再配布できる ⚫ Oracle JDKと中身はほとんど同じ ⚫
ただし、本家サイトでのバイナリ配布は ◼ x86-64版のみ ◼ zip/tar.gzアーカイブのみ #javajo 39/137
Public JRE配布の廃止 #javajo 40/137
WORA! ⚫ Javaのプログラムはどこでも動く Write Once, Run Anywhere! ⚫ OSがUnixでもWindowsでも ⚫
CPUがx86でもSparcでもARMでも ⚫ ただし、Javaがインストールされていれば #javajo 41/137
WORAの前提としてのPublic JRE ⚫ Public JREは、一般ユーザ向けに Sun/Oracleが配布していたJava処理系 ◼ 「あなたとJAVA, 今すぐダウンロード」 ⚫
AppletプラグインやJava Web Startも含む → いずれもJava SE 11で廃止 ⚫ Java SE 11では、 Public JREの配布が廃止された #javajo 42/137
時代の終わり ⚫ 「どこでもJavaが入っている」時代は 終わった ◼ iPhone登場時点で終わっていたのかも ◼ 今はむしろ、ブラウザとJavaScriptが WORAの担い手 #javajo
43/137
今後のJavaプログラム配布 ⚫ 今後Javaプログラムは、jlinkなどを使って、 Java処理系ごと配布する方式が 模索されている ◼ モジュールシステムが密接に関連 → 次章! #javajo
44/137
OpenJDKエコシステムの 活発化 #javajo 45/137
OpenJDKエコシステムの活発化 Java SE自体の進歩は、OpenJDKを中心に、 むしろ活発になっている ◼ クラウド・サーバサイド向けの 開発が加速 ◼ 多様なOpenJDKディストリビューション の登場
#javajo 46/137
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
開発の加速 加速するOpenJDK開発 ◼ たくさんの新GC方式 ◆ G1GC, ZGC, Shenandoah ◼ 起動時間の改善
◆ Class Data Sharing, AOT Compilation ◼ フットプリント削減: jlink ◼ 新JITコンパイラ: Graal ◼ 新仕様群: Panama, Vallhara, Loom, ... #javajo 48/137
OpenJDKディストロ 素のOpenJDKを使うのはハードルが高い ◼ バイナリ提供: x86-64版のみ ◼ パッケージング: zip/tar.gzアーカイブ → 各種OpenJDKディストリビューションに
注目が集まる #javajo 49/137
OpenJDKディストロ ⚫ AdoptOpenJDK ⚫ Red Hat OpenJDK ⚫ Azul Zulu
⚫ Amazon Corretto #javajo 50/137
#javajo AdoptOpenJDK ⚫ AdoptOpenJDK ⚫ 様々なプラットフォーム向けに OpenJDKをビルド・テストして提供する、 コミュニティベースのプロジェクト ⚫ Windows
(x86, x86-64), Mac, Linux (x86-64, Power, ARM64) ⚫ LTS版は最短4年アップデートを提供 51/137
#javajo Red Hat OpenJDK ⚫ Red HatによるOpenJDKパッケージ ⚫ GC実装としてShenandoahが含まれる ⚫
Red Hat Enterprise Linux, Windows ⚫ 提供バージョンを最短6年アップデート ⚫ 商用サポートあり 52/137
#javajo Azul Zulu ⚫ Zulu ⚫ Java処理系専業企業であるAzul Systemsが 提供するディストロ ⚫
Windows (x86-64), Mac, Linux (x86-64, ARM64) ⚫ LTS版について8年アップデート ⚫ 商用サポートあり 53/137
#javajo Amazon Corretto ⚫ Amazon Corretto ⚫ Amazon Linuxにバンドルしていた OpenJDKをパッケージ化したもの
⚫ Windows (x86, x86-64), Mac, Linux (x86-64) ⚫ 2018年12月時点でOpenJDK 11は未提供 54/137
注意! Ubuntu公式パッケージ ⚫ Ubuntu 18.04 のopenjdk-ltsパッケージは OpenJDK 10にセキュリティパッチを適用 したもの (2018年12月時点)
⚫ Bug #1796027 #javajo 55/137
Q. 結局なにを使えば良いの? #javajo 56/137
#javajo Q. 結局なにを使えば良いの? A. 場合による 要件として検討するべき項目: ◼ Javaを動かすプラットフォームは? ◼ 何年後にメジャーアップデートする?
◼ パッチ適用の頻度・機会・方式は? ◼ 商用サポートは必要? ◼ …… 57/137
Javaをとりまく環境の変化 小まとめ #javajo 58/137
#javajo Javaをとりまく環境の変化 ⚫ Javaはえらい勢いで変わっている ◼ 昔: いつでもどこでも動く夢の処理系 ◼ 今: 実用的で先鋭的なサーバサイド環境
⚫ 使う側も実用的で先鋭的になる必要がある 59/137
演目 Java SE, JDKってなんだっけ Java SEをとりまく環境の変化 モジュールシステムとjlink #javajo 60/137
モジュール・システム このセクションの目的: ◼ モジュール・システム対応に向けて、 心の準備ができること #javajo 61/137
モジュール・システム 内容: ◼ モジュール・システム導入の背景 ◼ モジュール・システムの基本 ◼ リフレクション ◼ コンパイルと実行
◼ モジュール世界への移行 ◼ モジュールのテスト ◼ jlink ◼ 高度なトピック #javajo 62/137
モジュール・システム 導入の背景 #javajo 63/137
Java 8までの課題 ⚫ JAR地獄 ⚫ 「内部向けパッケージ」の存在 ⚫ Java処理系の肥大化 #javajo 64/137
JAR地獄 #javajo 65/137
~Java 8: JAR地獄 ⚫ JAR地獄 := 大量のJARがクラスパスに 展開されて、混沌にブチ込まれること ◼ 「このJARいらないんじゃない?」
◼ → 消したら実行時エラー ⚫ Maven, Gradleのような依存性管理 ツールを使えば少しはマシだけど…… #javajo 66/137
~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
内部向けパッケージ #javajo 68/137
~Java 8: 内部向けパッケージ ⚫ プラットフォームやライブラリ内で、 「内部向け」パッケージを作ることがある ◼ org.kink_lang.kink.internal.xxx ◼ sun.misc
(JDK内) ⚫ 内部向けパッケージは本来、ライブラリ外 からの使用を想定していない ⚫ が、しかし #javajo 69/137
~Java 8: 内部向けパッケージ GitHubで“import sun.misc.Unsafe”を検索 #javajo 70/137
~Java 8: 内部向けパッケージ #javajo 71/137
~Java 8: 内部向けパッケージ ⚫ 内部使用向けのはずのUnsafeクラスが広く 使われてしまっている ◼ 性能を絞り出すため…… ⚫ なにが問題か?
◼ 移植性の低いプログラムの蔓延 ◼ 既存のプログラムを壊さないように配慮 すると、実装の改善がしづらい #javajo 72/137
Java処理系の肥大化 #javajo 73/137
#javajo 従来のサーバサイドデプロイ方式 従来はAPサーバにWAR/EARを置いていた Java処理系(OpenJDK等) APサーバ(Glassfish, JBoss等) WAR/EARファイル OS(カーネル+ユーザランド) こ こ
の サ イ ズ は 大 し て 気 に し な い 74/137
#javajo 最近のサーバサイドデプロイ方式 最近はJava処理系を含むコンテナをデプロイ OS(カーネル+ユーザランド) コンテナホスト(Docker等) コンテナ OS(ユーザランドのみ) Java処理系(OpenJDK等) JARファイル サイズが大きいと
デプロイが苦しい 75/137
~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
#javajo ~Java 8: Java処理系の肥大化 アプリが使う機能はJava処理系のごく一部 ◼ サーバサイドアプリにSwingは不要 ◼ 制御系組込みシステム以外でCORBAが 使われることはまれ
使わない機能がフットプリントの大部分を 占めることはやるせない 77/137
モジュール・システムの基本 #javajo 78/137
モジュール・システム ⚫ JARを名前付きのモジュールとして、 カプセル化された配置の単位に ⚫ JAR地獄 → モジュール単位で依存関係を整理 ⚫ 内部向けパッケージ
→ 外部からの使用を実質的に制限 ⚫ Java処理系の肥大化 → jlinkでカスタムのJava処理系を作成 #javajo 79/137
モジュール・システム 各JARファイルが名前付きのモジュールに ace-shooter.jar = module net.example.ace_shooter matrix.jar = module org.example.matrix
physics.jar = module jp.example.physics モジュール名は逆ドメイン名方式が推奨 #javajo 80/137
パッケージ衝突の検知 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
module-info.java モジュール名はソースディレクトリのトップ レベルのmodule-info.javaで宣言 module org.example.matrix { } JARファイルのトップレベルの module-info.class コンパイル
#javajo 82/137
公開パッケージの指定 module org.example.matrix { exports org.example.matrix.api; } モジュールは、他のモジュールに対して公開 するパッケージをexports命令で指定する exportされたパッケージは
モジュールの外部仕様 の一部とみなせる #javajo 83/137
使うモジュールの指定 module jp.example.physics { requires org.example.matrix; } モジュールは、自分が使うモジュールを、 requires命令で指定する モジュールが使えるクラスの条件:
⚫ requiresした先のモジュールの ⚫ exportsされたパッケージの ⚫ publicなクラス → 該当しないクラスを使うと コンパイルエラー / 実行時例外 #javajo 84/137
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
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
exports / requires module A { requires B; } module
B { exports B.api; requires C; } requiresしたモジュールが存在しないと コンパイルエラー / 実行時例外 #javajo 87/137
標準モジュール 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
リフレクション #javajo 89/137
リフレクション モジュールのカプセル化はリフレクションに も適用される ◼ 外部モジュールからアクセスできるのは、 exportsされたパッケージの、 公開クラスの、 公開メンバだけ ◆ requires関係は不要
◼ 非公開なメンバへのアクセスは、 外部モジュールからは通常不可能 #javajo 90/137
リフレクション 困る例: DI先のクラス package net.example.ace_shooter.engine; public class GameEngine { @Inject
private PerfMonitor perfMonitor; ... } public にしたくない exportsしたくない リフレクションで触ってほしいクラスは 必ずしも公開したいわけではない #javajo 91/137
リフレクション 必要な緩和策: ◼ パッケージをexportsしたくない ◼ メンバをpublicにしたくない ◼ でもリフレクションでアクセスさせたい #javajo 92/137
opens命令 opens命令でパッケージを指定することで、 外部からリフレクションができるようになる module net.example.ace_shooter { opens net.example.ace_shooter.core; ... }
#javajo 93/137
openモジュール モジュール宣言にopenを修飾すると、 すべてのパッケージがopens指定される open module net.example.ace_shooter { ... } #javajo
94/137
リフレクション リフレクションは もはや魔法の杖ではない! #javajo 95/137
コンパイルと実行 #javajo 96/137
コンパイルと実行 注意点: ◼ プログラムのコンパイル方法、実行時の プログラム配置方法はJava SE実装依存 ◼ 本セッションは、Java SEの参照実装で あるOpenJDKを前提とする
#javajo 97/137
モジュールパス モジュールパス: ◼ モジュールのJARファイルを配置する パス ◼ クラスパスとは別! #javajo 98/137
コンパイル javacコマンドの主なオプション オプション 内容 --module-path ¥ {モ ジ ュ ー
ル パス} 依存先モジュールの配置場所 --module-source-path ¥ {モジュールソースパス} 複数モジュールを同時コンパイル する時、モジュールのソースディ レクトリの配置場所 ※あまり使わないはず --module-version ¥ {バ ー ジ ョン} モジュールのバージョン ※いまのところ使い道は無い #javajo 99/137
ブートレイヤー 実行 初期モジュール(mainを含むモジュール)か ら推移的に参照されるモジュール、および SPIの実装を提供するモジュールが ブートレイヤー(実行時の構成)に含まれる module Main java.base java.desktop
java.sql module X module Y module Z モ ジ ュ ー ル パ ス #javajo 100/137
実行 javaコマンドの主なオプション オプション 内 容 --module-path ¥ {モ ジ ュ
ー ル パス} モ ジ ュ ー ル の 場 所 --module ¥ {初 期 モ ジ ュ ー ル名}/{メインクラス } mainメソッドを持つ ク ラ ス --module {初期モジュール 名} 初 期 モ ジ ュ ー ル --add-modules ¥ {モ ジ ュ ー ル名},{モジュール名},... 指定したモジュール を ブ ー ト レ イ ヤ ー に 追 加 #javajo 101/137
経過措置 #javajo 102/137
経過措置 ⚫ 現時点で、多くのプログラムのJARは、 module-info.classを含んでいない ⚫ モジュールの世界への経過措置として、 二種類の特殊なモジュールが導入された ◼ 無名モジュール ◼
自動モジュール #javajo 103/137
無名モジュール ⚫ クラスパス上のクラスファイルは、 無名モジュールの中でロードされる ⚫ 無名モジュールは: ◼ モジュール名を持たない ◼ すべてのモジュールをrequiresする
◼ すべてのパッケージをexportsする ◼ (Java SE実装依存)外部モジュールの 非公開メンバへのリフレクションが可能 #javajo ‡ 104/137
自動モジュール ⚫ モジュールパス上のJARファイルのうち、 module-info.classを持たないものは、 自動モジュールとしてロードされる ⚫ 自動モジュールは: ◼ モジュールパス上の すべてのモジュールをrequiresする
◼ すべての無名モジュールをrequiresする ◼ すべてのパッケージをexportsする ◼ すべてのパッケージをopensする #javajo 105/137
自動モジュール 自動モジュールのモジュール名の決定方法: 1. JARのMANIFEST.MFファイルが Automatic-Module-Name属性を持って いる場合、その値がモジュール名 2. そうでない場合、JARファイル名を元に モジュール名が作られる ◆
commons-io.jar → commons_ioモジュール #javajo 106/137
モジュール世界への移行 #javajo 107/137
モジュール世界への移行 ソフトウェア種別ごとのモジュール化指針: 種別 モジュール化指針 ライブラリ いますぐモジュール化! プラグイン 基盤ミドルウェア次第 APサーバ上の アプリケーション
基盤ミドルウェア次第 ※Java EE 8はモジュール非対応 スタンドアロンの アプリケーション 遅くなりすぎない程度に モジュール化する場合もしない場合も、 JDK9への移行ガイドは必読 #javajo 108/137
ライブラリのモジュール化 ライブラリのモジュール化が喫緊な理由: ◼ ライブラリを使う側のプログラムが、 requires命令を書けるようにするため #javajo 109/137
ライブラリのモジュール化 JARファイル名ベースの自動モジュールを requiresしてはいけない! module org.example.matrix { requires commons_io; ... }
駄目パターン: → Commons IOに本当のモジュール名が 付いたとき、ライブラリを使う側のプログラムが 不整合になる ※ requires staticは許容範囲 #javajo 110/137
ライブラリのモジュール化 モジュール化のフロー すべてのrequires先JARの モジュール名が決まるまで待つ Automatic-Module-Nameで モジュール名を決めて公開 module-info.javaを書いて公開 すべての requires先JAR の
モジュール名が決まっている? No Yes #javajo 111/137
ライブラリのモジュール化 Java SE 8以前をサポートしたい時: ◼ Automatic-Module-Name属性を付ける → これは簡単 ◼ module-info.javaが書きたい場合、
module-info.javaだけをJava SE 9用に コンパイルする #javajo 112/137
モジュールのテスト #javajo 113/137
モジュールのテスト 二種類のテスト ブ ラ ッ ク ボ ッ ク ス
・テスト ⚫ モ ジ ュ ー ル の 外 か ら テ スト 。 ⚫ exportsされたパッケージの、public な ク ラ ス を 操 作 し て 、 仕 様ど お りに 動 く こ と を 確 か め る 。 ⚫ テ ス ト コ ー ド は 、 テ ス ト対 象 と 別 モ ジ ュ ー ル 。 ホ ワ イ ト ボ ッ ク ス ・テスト ⚫ モ ジ ュ ー ル の 内 側 を テ スト 。 ⚫ 公 開・非公開にかかわらず、クラ ス・ メソッドを操作して、意図した実装に な っ て い る こ と を 確 か める 。 ⚫ テ ス ト コ ー ド は 、 テ ス ト対 象 と 同 一 モ ジ ュ ー ル……どうやって? #javajo 114/137
ホワイトボックス・テスト ホワイトボックス・テストの課題: ◼ テストコードは、JUnit, TestNG, JMockit など、テスト用ライブラリを使う ◆ テスト対象コードは、これらのライブ ラリをrequiresしていない
◼ コンパイル済みのモジュールに、テスト コードのクラスを追加する必要がある #javajo 115/137
ホワイトボックス・テスト ふたつのやり方: 正攻法 → こちらを解説 ⚫ テスト対象のモジュール定義を、 テストできる構成に一時的に上書き ⚫ javac/javaコマンドにオプションを指定
次善の策 ⚫ あきらめてクラスパス上でテスト #javajo 116/137
モジュール定義の上書き JDKのjavac/javaコマンド共通オプション オプション 内 容 --add-reads ¥ {モ ジ ュ
ー ル名}={参照先モジュール},... requires定義を追加 --patch-module ¥ {モ ジ ュ ー ル名}={ファイル,...},... モ ジ ュ ー ル に ソ ー ス フ ァ イ ル/クラス フ ァ イ ル を 追 加 #javajo 117/137
モジュール定義の上書き 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
jlink #javajo 119/137
#javajo jlink jlink ◼ 必要なモジュールだけを含んだカスタム のJava処理系を生成するツール ◼ jlinkコマンドとしてJDKに付属する ◼ 対応するJSRは無い
120/137
#javajo jlink登場の背景 ⚫ コンテナに同梱するJava処理系は、サイズ を小さくしたい ⚫ 「どこにでもJavaが入っている」ことは、 もはや期待できない。Javaプログラムを配 る際には、Java処理系自体の配布も合わせ て設計する必要がある
121/137
基本的な使い方 #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
主なコマンドラインオプション #javajo オプション 内容 --module-path {モ ジ ュ ー ル
パ ス} モジュールを探す場所 --add-modules ¥ {モ ジ ュ ー ル1},{モジュール2},... 処理系に追加する モジュールの起点 --bind-services SPIの実装を提供するモ ジュールも処理系に含む --launcher { コ マ ン ド 名 }={初期 モジュール }/{メインクラス} mainメソッドを持つクラ ス --launcher { コ マ ン ド 名 }={初期 モジュール } 初期モジュール --output {出力先ディレクトリ} 処理系の出力先 123/137
#javajo 処理系に含まれるモジュール 次のモジュールが処理系に含まれる ◼ --add-modulesオプションで指定した モジュール ◼ 処理系に含まれるモジュールから requiresされるモジュール ◼
処理系に含まれるモジュールがusesする サービスの実装をprovidesする モジュール(→次章) 124/137
#javajo プラットフォームに関する注意 ⚫ 生成されるJava処理系は、 プラットフォーム固有のもの ⚫ Windows用のJava処理系を生成するには、 Windows上でjlinkを実行する必要がある 125/137
#javajo ライセンスに関する注意 ⚫ OTNライセンスにもとづいてjlinkを実行し た場合、生成されるJava処理系にもOTNラ イセンスが(おそらく)適用される ◼ この場合、生成されるJava処理系を本番 用途で使うことは(おそらく)できない ⚫
カスタム処理系をひっくるめて納品する 場合、処理系自体のライセンスに抵触しな いようにする必要がある 126/137
高度なトピック #javajo 127/137
ServiceLoader/SPI ServiceLoader/SPIの仕組みは モジュール・システムに統合された ◼ サービスを使うモジュールは、 uses命令でサービスのインタフェースを 指定 ◼ サービスを提供するモジュールは、 provides命令でサービスの実装を指定
#javajo 128/137
requires static コンパイル時に必要だが、実行時には不要な モジュールがrequires static命令で指定できる ◼ 例: JSR 305の@Nullableアノテーション #javajo
129/137
ブートレイヤー モジュールレイヤー モジュールレイヤー: モジュールの名前空間 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
モジュールレイヤー クラスローダーとモジュールレイヤーの関連 Module ModuleLayer ClassLoader Class Package Unnamed Module Named
Module http://d.hatena.ne.jp/miyakawa_taku/20171108/1510145001 #javajo 131/137
OSGiとの違い ⚫ OSGiはロード・関連付けするミドルウェア を仕様に含むが、 Javaのモジュール・システムは含まない ⚫ Javaのモジュール・システムは、OSGiの ようなものを作るための基礎と考えられる #javajo 132/137
モジュール・システムの 参考資料 #javajo 133/137
モジュール・システムの参考資料 Bakker, Mak (2017)『Java 9 Modularity』 #javajo 134/137
註釈 #javajo 135/137
† パッケージの衝突検知 「複数のモジュールが同一パッケージを含む場 合、起動時に検知される」 ◼ 厳密には、「モジュールレイヤーが、モ ジュール間のパッケージ重複を許さない構 成である時、そのモジュールレイヤー内の 複数のモジュールが~」である ◼
異なるモジュールレイヤー間では、同じ名 前のパッケージが共存できる ◼ defineModulesWithManyLoadersで作られた モジュールレイヤーは、exportされない パッケージの重複を許す #javajo 136/137
‡ 強固なカプセル化の緩和 「(Java SE実装依存)外部モジュールの非公 開メンバへのリフレクションが可能」 ◼ Java SE 9仕様(JSR 379)では、Java
SE実装が、このような動作をデフォル トとしてもよい、と規定されている (Relaxing strong encapsulation節) #javajo 137/137