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
1.9k
ミニバッチサイズと学習率の関係 /small-batch-learning
miyakawataku
0
2k
機械学習プロジェクトの進め方 /howtoproceedwithmlproject
miyakawataku
0
330
グラフアルゴリズムその2: 単一始点最短路問題 /graphShortestPaths
miyakawataku
0
150
Strassenのアルゴリズムによる行列積の計算 /strassen-algorithm
miyakawataku
8
3k
Viterbiのアルゴリズム /viterbi-algorithm
miyakawataku
0
250
Other Decks in Programming
See All in Programming
どうして僕の作ったクラスが手続き型と言われなきゃいけないんですか
akikogoto
1
120
Ethereum_.pdf
nekomatu
0
460
リアーキテクチャxDDD 1年間の取り組みと進化
hsawaji
1
220
見せてあげますよ、「本物のLaravel批判」ってやつを。
77web
7
7.7k
ローコードSaaSのUXを向上させるためのTypeScript
taro28
1
610
ECS Service Connectのこれまでのアップデートと今後のRoadmapを見てみる
tkikuc
2
250
Amazon Qを使ってIaCを触ろう!
maruto
0
400
ペアーズにおけるAmazon Bedrockを⽤いた障害対応⽀援 ⽣成AIツールの導⼊事例 @ 20241115配信AWSウェビナー登壇
fukubaka0825
6
1.9k
よくできたテンプレート言語として TypeScript + JSX を利用する試み / Using TypeScript + JSX outside of Web Frontend #TSKaigiKansai
izumin5210
6
1.7k
Webの技術スタックで マルチプラットフォームアプリ開発を可能にするElixirDesktopの紹介
thehaigo
2
1k
Realtime API 入門
riofujimon
0
150
聞き手から登壇者へ: RubyKaigi2024 LTでの初挑戦が 教えてくれた、可能性の星
mikik0
1
130
Featured
See All Featured
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
126
18k
Writing Fast Ruby
sferik
627
61k
GraphQLとの向き合い方2022年版
quramy
43
13k
Designing for humans not robots
tammielis
250
25k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
860
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Side Projects
sachag
452
42k
Practical Orchestrator
shlominoach
186
10k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
329
21k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Scaling GitHub
holman
458
140k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
93
16k
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