JDK 13 へようこそ
• JVM Sustaining Engineer
• OpenJDK Update Project
Maintainer
• JavaOne Rock Star
• Co-author of Oracle WebLogic
Server 11g 構築・運用ガイド
• @DavidBuckJP
• https://blogs.oracle.com/buc
k/
Who am I? バック デイビッド(左)
Agenda
• 350: Dynamic CDS Archives
• 351: ZGC: Uncommit Unused Memory
• 353: Reimplement the Legacy Socket API
• 354: Switch Expressions (Preview)
• 355: Text Blocks (Preview)
Agenda
• 350: Dynamic CDS Archives
• 351: ZGC: Uncommit Unused Memory
• 353: Reimplement the Legacy Socket API
• 354: Switch Expressions (Preview)
• 355: Text Blocks (Preview)
Agenda
• 350: Dynamic CDS Archives
• 351: ZGC: Uncommit Unused Memory
• 353: Reimplement the Legacy Socket API
• 12: Preview Language and VM Features
• 354: Switch Expressions (Preview)
• 355: Text Blocks (Preview)
JEP 350
Dynamic CDS Archives
Class Data Sharing
java
(JVM)
クラスデータ
(メモリ上)
java
(JVM)
クラスデータ
(メモリ上) java
(JVM)
クラスデータ
(メモリ上)
java
(JVM)
クラスデータ
(メモリ上)
Class Data Sharing
java
(JVM)
java
(JVM)
java
(JVM)
java
(JVM)
クラスデータ
classes.jsa
Class Data Sharing の歴史
• 2004 Class Data Sharing - JDK 5
• 2015 Application Class Data Sharing - JDK 8u40 and JDK 9
(Closed Source)
• 2018 JEP 310: Application Class Data Sharing - JDK 10 (Open
Source)
Class Data Sharing の魅力
• 起動時間を早くする
• 複数の JVM のメモリ使用量を減らす
Class Data Sharing の歴史
• 2004 Class Data Sharing - JDK 5
• 2015 Application Class-Data Sharing - JDK 8u40 and JDK 9
(Closed Source)
• 2018 JEP 310: Application Class-Data Sharing - JDK 10
(Open Source)
Class Data Sharing の歴史
• 2004 Class Data Sharing - JDK 5
• 2015 Application Class-Data Sharing - JDK 8u40 and JDK 9
(Closed Source)
• 2018 JEP 310: Application Class-Data Sharing - JDK 10
(Open Source)
Class Data Sharing (JDK 5 以来)
• Java SE のクラスライブラリ(rt.jar) のみ
• jre/lib/[arch]/client/classes.jsa
Class Data Sharing (JDK 5 以来)
• Xdump
• -Xshare:dump
• -Xshare:off
• -Xshare:on
• -Xshare:auto (デフォルト)
Application Class Data Sharing(JDK 8u40)
• アプリケーションのクラスもアーカイブ出来る
• -XX:SharedClassListFile でアーカイブを指定する
Application Class Data Sharing(JDK 8u40)
1. ロードされるクラスを確認する
2. 1で確認したクラスを指定して、アーカイブを作成する
3. 実行時にアーカイブを指定する
ロードされるクラスを確認する
$ java -Xshare:off -XX:+UseAppCDS
-XX:DumpLoadedClassList=hello.lst -cp hello.jar HelloWorld
確認したクラスを指定して、
アーカイブを作成する
$ java -Xshare:dump -XX:+UseAppCDS
-XX:SharedClassListFile=hello.lst
-XX:SharedArchiveFile=hello.jsa -cp hello.jar
実行時にアーカイブを指定する
$ java -Xshare:on -XX:+UseAppCDS
-XX:SharedArchiveFile=hello.jsa -cp hello.jar HelloWorld
Application Class Data Sharing(JDK 8u40)
1. ロードされるクラスを確認する
2. 1で確認したクラスを指定して、アーカイブを作成する
3. 実行時にアーカイブを指定する
Application Class Data Sharing(JDK 8u40)
1. ロードされるクラスを確認する
2. 1で確認したクラスを指定して、アーカイブを作成する
3. 実行時にアーカイブを指定する
Dynamic CDS Archives(JDK 13)
1. アーカイブを作成する
2. 実行時にアーカイブを指定する
アーカイブを作成する
$ java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
アーカイブを作成する
$ java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
実行時にアーカイブを指定する
$ java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello
2重の構成
Static
Dynamic
2アプリ物語
$ java -cp:lib.jar:foo.jar FooApp
$ java -cp:lib.jar:bar.jar BarApp"
2アプリ物語
$ java -cp:lib.jar:foo.jar FooApp
$ java -cp:lib.jar:bar.jar BarApp"
2アプリ物語
$ java -cp:lib.jar:foo.jar FooApp
$ java -cp:lib.jar:bar.jar BarApp"
Class Data Sharing
java
(JVM)
java
(JVM)
java
(JVM)
java
(JVM)
static
rt.jar
lib.jar
foo.jar
bar.jar
JEP 351
ZGC: Uncommit Unused
Memory
ZGC: Uncommit Unused Memory
利用されていない Java ヒープ領域を OS に戻す(解放する)
ZGC: Uncommit Unused Memory
利用されていない Java ヒープ領域を OS に戻す(解放する)
G1GC と Shenandoah はもう実装済み
メモリ解放する魅力
• メモリ使用量によってコストが変わる (例:container / cloud)
• 長期間のアイドル (例:Serverless)
• 起動処理(Startup) vs. 運用中(Steady State)
ZPages
ZPageCache
ZPage を Least Recently Used (LRU)の順番で管理する
ZUncommitDelay
-XX:ZUncommitDelay=<秒> (デフォルト5分)
ZUncommitDelay
-XX:ZUncommitDelay=<秒> (デフォルト5分)
-XX:ShenandoahUncommitDelay=<ミリ秒>
Linux の動作環境
• ZGC は tmpfs か hugetlbfs が利用される
• fallocate() の FALLOC_FL_PUNCH_HOLE サポートが必要
• Tmpfs - Linux 3.5 以降
• Hugetlbfs – Linuc 4.3 以降
Xms != Xmx ??
• Xms と Xmx が異ならないかぎり、この機能は動作しない
• クラウド時代では、
Xms == Xmx がベストプラクティスではない場合がある
クラウド時代
• 350: Dynamic CDS Archives
• 351: ZGC: Uncommit Unused Memory
JEP 353
Reimplement the Legacy
Socket API
まず、脱線。。。
JEP 312 (JDK 10)
Thread-Local Handshakes
従来の safepoint (STW)
JEP 312 (JDK 10)
Thread-Local Handshakes
従来の safepoint (STW) • TLH の実装
Thread-Local Handshakes
• 内部実装の変更だけ
• 将来バージョンの機能(主に ZGC)の為のもの
• 新しいのリリースモデル(6か月ごと)
一つの大規模の変更 -> 複数の小規模の変更
JEP 353
Reimplement the Legacy Socket API
• ソケットの実装を書き直しました。
• 主に将来バージョンの機能(Project Loom) のため
• 従来の実装よりメンテナンスしやすい
ソケットの新しい実装
• NIO ベース(実績のあるネイティブ実装)
• 入出力バッファはスタックで格納されない
普通の off-heap バッファーを利用する
• Monitor -> java.util.concurrent のロック
ソケットの新しい実装
• NIO ベース(実績のあるネイティブ実装)
• 入出力バッファはスタックで格納されない
普通の off-heap バーファーを利用する
• Monitor -> java.util.concurrent のロック
Loom プロジェクト
• Loom は j.u.c のロックを使うスレッドの処理を最適する
• ソケットの新しい実装は従来より Loom の効果を得られる見込み
要注意
• 20年以上に渡った従来の実装をリプレースした
• 非互換性などの副作用がある
既知問題については JEP をご参考下さい
• 一時的な回避策として、jdk.net.usePlainSocketImpl という
システムプロパティで従来の実装を利用することが出来る
JEP 12
Preview Language and VM
Features
Preview 機能
• 主に仕様の変更や追加
• Java Platform の正式の一部(必須)
• 実装は完全(機能の面、品質の面)
• 将来になくなる、あるいは、変わる可能性がある
ビルド (JDK 13 の場合)
javac Foo.java // preview 機能は利用出来ない
javac --release 13 --enable-preview Foo.java
// preview 機能は利用出来る
javac --release 12 --enable-preview Foo.java
// ダメ!バージョンが異なる
実行
java Foo // preview 機能を利用するクラスをロード出来ない
java --enable-preview Foo
// 同じ JDK のバージョンの javac でビルドしたクラス
(preview 機能有効)をロード出来る
Demo
JEP 354
Switch Expressions (Preview)
Switch Expressions の歴史
• JEP 325: Switch Expressions (Preview) JDK 12
• JEP 354: Switch Expressions (Preview) JDK 13
• JEP 361: Switch Expressions (Standard) JDK 14 ★
Switch Expressions の歴史
• JEP 325: Switch Expressions (Preview) JDK 12
• JEP 354: Switch Expressions (Preview) JDK 13
• JEP 361: Switch Expressions (Standard) JDK 14 ★
★だといいな。。。
従来の Switch 文の弱点
• 一つのスコープブロックしかない
• フォールスルー
• 式として利用出来ない
スコープの問題
switch (day) {
case MONDAY:
case TUESDAY:
int temp = ... // temp のスコープは ‘}’ まで続く
break;
case WEDNESDAY:
case THURSDAY:
int temp2 = ... // temp を再利用出来ず
break;
default:
int temp3 = ... // temp を再利用出来ず
}
フォールスルー
• C / C++ のまま利用されました
• システムプログラミングで役に立つユースケースはある
• よりハイレベルだと、ユースケースはあまりない
• break 文を忘れるバグが非常に多い
• break 文のせいでコードが読みにくくなる
int numLetters;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numLetters = 6;
break;
case TUESDAY:
numLetters = 7;
break;
case THURSDAY:
case SATURDAY:
numLetters = 8;
break;
case WEDNESDAY:
numLetters = 9;
break;
default:
throw new
IllegalStateException("Wa
t: " + day);
}
int numLetters;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numLetters = 6;
break;
case TUESDAY:
numLetters = 7;
break;
case THURSDAY:
case SATURDAY:
numLetters = 8;
break;
case WEDNESDAY:
numLetters = 9;
break;
default:
throw new
IllegalStateException("Wa
t: " + day);
}
int numLetters = 式
int numLetters =
boolVal ? 13 : 42;
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
switch 文から switch 式へ
• より読みやすい
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
Arrow Labels (矢印のラベル)
• フォールスルーなし
• switch 式だけではなく、switch 文でも利用可能
switch 文と Arrow Labels
static void howMany(int k) {
switch (k) {
case 1 -> System.out.println("one");
case 2 -> System.out.println("two");
default -> System.out.println("many");
}
}
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
複数のラベル
フォールスルーがなければ、不可欠
yield キーワード
int result = switch (s) {
case "Foo":
yield 1;
case "Bar":
yield 2;
default:
System.out.println("Neither Foo nor Bar,
hmmm...");
yield 0;
};
break 42; -> yield 42;
• JDK 12 は break 文を利用し、値を返す
• Preview のフィードバックによると、混乱しやすかった
• JDK 13 では値を返す break が yield でリプレースされた
break の従来の振舞は変更ぜす
値を返す必要性
各アームが値を yield するか、例外をスローする
値を返す必要性
int i = switch (day) {
case MONDAY -> {
System.out.println("Monday");
// ダメ!Yield がない
}
default -> 1;
};
値を返す必要性
int i = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY:
yield 0;
default:
System.out.println("Second half of the
week");
// ダメ! yield がない!
};
JEP 355
Text Blocks (Preview)
Toothpick Syndrome
(爪楊枝症候群)
Path path = Paths.get("C:¥¥Program Files¥¥foo");
Pattern pattern = Pattern.compile("¥¥¥"");
By Superbass - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=44882037
String html = "<html>¥n" +
" <body>¥n" +
" <p>Hello, world</p>¥n" +
" </body>¥n" +
"</html>¥n";
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
String query =
"SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`¥n" +
"WHERE `CITY` = 'INDIANAPOLIS'¥n" +
"ORDER BY `EMP_ID`, `LAST_NAME`;¥n";
String query =
"""
SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
WHERE `CITY` = 'INDIANAPOLIS'
ORDER BY `EMP_ID`, `LAST_NAME`;
""";
ScriptEngine engine =
new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval("function hello() {¥n" +
" print('¥"Hello, world¥"');¥n" +
"}¥n" +
"¥n" +
"hello();¥n");
ScriptEngine engine =
new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval("""
function hello() {
print('"Hello, world"');
}
hello();
""");
• JEP 326: Raw String Literals (Preview)
• JEP 355: Text Blocks (Preview) JDK 13
• JEP 368: Text Blocks (Second Preview) JDK 14 ★
• JEP 326: Raw String Literals (Preview)
• JEP 355: Text Blocks (Preview) JDK 13
• JEP 368: Text Blocks (Second Preview) JDK 14 ★
★だといいな。。。
まとめ
JDK 13
• 350: Dynamic CDS Archives
• 351: ZGC: Uncommit Unused Memory
• 353: Reimplement the Legacy Socket API
• 354: Switch Expressions (Preview)
• 355: Text Blocks (Preview)
JDK 13
• 350: Dynamic CDS Archives
• 351: ZGC: Uncommit Unused Memory
• 353: Reimplement the Legacy Socket API
• 354: Switch Expressions (Preview)
• 355: Text Blocks (Preview)
Thank You!!!

JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]