Welcome, Java 15!
JJUG Night Seminar
#JJUG
Who am I?
https://logico-jp.io
参考資料
blogs.oracle.com/java-platform-group/the-arrival-of-java-15
logico-jp.io/2020/09/16/the-arrival-of-java-15/
logmi.jp/tech/articles/323179
www.slideshare.net/YujiKubota/head-toward-java-14-and-java-15-linedm
qiita.com/nowokay/items/2858699bc1cd89222cd8
www.javainthebox.com/2020/09/jepjava-se-15.html
Thanks for your watching…
Thanks for your watching…
It’s too early!
Agenda
Java 15 (not 1.5)
JSR 390 : Java SE 15
cr.openjdk.java.net/~iris/se/15/lat
estSpec/apidiffs/overview-
summary.html
リリースサイクル変更後6回⽬のリリース
The 6th release since release cadence was changed
Java 8 Java 9
2017/9 2018/3 2018/9 2019/3 2019/9 2020/3 2020/9 2021/3 2021/9
2020/09/15 2021/03/15
Contributors
blogs.oracle.com/java-platform-group/the-arrival-of-java-15
JDK 15までのJEPの個数 – # of JEPs in each release
blogs.oracle.com/java-platform-group/the-arrival-of-java-15
JDK 15に取り込まれたJEP – JEPs in JDK 15
openjdk.java.net/projects/jdk/15/
339 Edwards-Curve Digital Signature Algorithm (EdDSA)
360 Sealed Classes (Preview)
371 Hidden Classes
372 Remove the Nashorn JavaScript Engine
373 Reimplement the Legacy DatagramSocket API
374 Disable and Deprecate Biased Locking
375 Pattern Matching for instanceof (Second Preview)
377 ZGC: A Scalable Low-Latency Garbage Collector
378 Text Blocks
379 Shenandoah: A Low-Pause-Time Garbage Collector
381 Remove the Solaris and SPARC Ports
383 Foreign-Memory Access API (Second Incubator)
384 Records (Second Preview)
385 Deprecate RMI Activation for Removal
廃⽌や削除
Removed or deprecated
339 Edwards-Curve Digital Signature Algorithm (EdDSA)
360 Sealed Classes (Preview)
371 Hidden Classes
372 Remove the Nashorn JavaScript Engine
373 Reimplement the Legacy DatagramSocket API
374 Disable and Deprecate Biased Locking
375 Pattern Matching for instanceof (Second Preview)
377 ZGC: A Scalable Low-Latency Garbage Collector
378 Text Blocks
379 Shenandoah: A Low-Pause-Time Garbage Collector
381 Remove the Solaris and SPARC Ports
383 Foreign-Memory Access API (Second Incubator)
384 Records (Second Preview)
385 Deprecate RMI Activation for Removal
新機能や追加機能
New or additional features
339 Edwards-Curve Digital Signature Algorithm (EdDSA)
360 Sealed Classes (Preview)
371 Hidden Classes
372 Remove the Nashorn JavaScript Engine
373 Reimplement the Legacy DatagramSocket API
374 Disable and Deprecate Biased Locking
375 Pattern Matching for instanceof (Second Preview)
377 ZGC: A Scalable Low-Latency Garbage Collector
378 Text Blocks
379 Shenandoah: A Low-Pause-Time Garbage Collector
381 Remove the Solaris and SPARC Ports
383 Foreign-Memory Access API (Second Incubator)
384 Records (Second Preview)
385 Deprecate RMI Activation for Removal
プレビューもしくはインキュベート機能
Preview or incubator projects
339 Edwards-Curve Digital Signature Algorithm (EdDSA)
360 Sealed Classes (Preview)
371 Hidden Classes
372 Remove the Nashorn JavaScript Engine
373 Reimplement the Legacy DatagramSocket API
374 Disable and Deprecate Biased Locking
375 Pattern Matching for instanceof (Second Preview)
377 ZGC: A Scalable Low-Latency Garbage Collector
378 Text Blocks
379 Shenandoah: A Low-Pause-Time Garbage Collector
381 Remove the Solaris and SPARC Ports
383 Foreign-Memory Access API (Second Incubator)
384 Records (Second Preview)
385 Deprecate RMI Activation for Removal
JEPs (Java Enhancement Proposal) in Java 15
Removed or deprecated
廃⽌や削除
Removed or deprecated
339 Edwards-Curve Digital Signature Algorithm (EdDSA)
360 Sealed Classes (Preview)
371 Hidden Classes
372 Remove the Nashorn JavaScript Engine
373 Reimplement the Legacy DatagramSocket API
374 Disable and Deprecate Biased Locking
375 Pattern Matching for instanceof (Second Preview)
377 ZGC: A Scalable Low-Latency Garbage Collector
378 Text Blocks
379 Shenandoah: A Low-Pause-Time Garbage Collector
381 Remove the Solaris and SPARC Ports
383 Foreign-Memory Access API (Second Incubator)
384 Records (Second Preview)
385 Deprecate RMI Activation for Removal
Remove the Nashorn JavaScript Engine
medium.com/graalvm/nashorn-removal-graalvm-to-the-rescue-d4da3605b6cb
logico-jp.io/2020/03/24/nashorn-removal-graalvm-to-the-rescue/
Disable and Deprecate Biased Locking
ž Java 15 からは biased locking をデフォルトで無効
Biased Locking
ž ロック実装は2種類
なぜデフォルトのロック実装になった?
Why biased locking was chosen at that time?
無効化する理由
Why has biased locking been disabled since Java 15?
参考資料
blogs.oracle.com/dave/biased-locking-in-hotspot
mechanical-sympathy.blogspot.com/2011/11/java-lock-implementations.html
Remove the Solaris and SPARC Ports
Deprecate RMI Activation for Removal
対象
What objects are targeted?
New or additional features
新機能や追加機能
New or additional features
339 Edwards-Curve Digital Signature Algorithm (EdDSA)
360 Sealed Classes (Preview)
371 Hidden Classes
372 Remove the Nashorn JavaScript Engine
373 Reimplement the Legacy DatagramSocket API
374 Disable and Deprecate Biased Locking
375 Pattern Matching for instanceof (Second Preview)
377 ZGC: A Scalable Low-Latency Garbage Collector
378 Text Blocks
379 Shenandoah: A Low-Pause-Time Garbage Collector
381 Remove the Solaris and SPARC Ports
383 Foreign-Memory Access API (Second Incubator)
384 Records (Second Preview)
385 Deprecate RMI Activation for Removal
Edwards-Curve Digital Signature Algorithm (EdDSA)
Hidden Classes
sun.misc.Unsafe::defineAnonymousClass を
Motivation
Fooというクラスにbarというメソッドがあるとして...
When Class 'Foo' has a method named 'bar'...
// Class is stored in byte array
byte[] bytes = Files.readAllBytes(Paths.get("Foo.class"));
MethodHandles.Lookup lookup = MethodHandles.lookup();
// Look up the hidden class
lookup.defineHiddenClass(bytes, false);
Class<?> clazz = lookup.findClass("Foo");
Constructor constuctor = clazz.getDeclaredConstructor();
Object hiddenClassInstance = constuctor.newInstance();
// Get method declared in the hidden class and invoke it
Method method = clazz.getDeclaredMethod("bar");
method.invoke(hiddenClassInstance);
注意点
java.lang.Error: thrown from hidden class com.example.Foo/0x0000000800b7a470
at m1/com.example.Foo/0x0000000800b7a470.toString(Foo.java:16)
at m1/com.example.Foo_0x0000000800b7a470$$Lambda$29/0x0000000800b7c040.apply(<Unknown>:1000001)
at m1/com.example.Foo/0x0000000800b7a470.test(Foo.java:11)
参考資料
blogs.oracle.com/javamagazine/the-unsafe-class-unsafe-at-any-speed
blogs.oracle.com/jrose/anonymous-classes-in-the-vm
Reimplement the Legacy DatagramSocket API
どのあたりが変わった?
openjdk.java.net/jeps/373
どれぐらいパフォーマンスに差が出るのか
Performance gain : JGroupsの例
0
10000
20000
30000
40000
50000
60000
70000
80000
90000
100000
UDP TCP
Throughput(req/sec)
JGroups 5.0.0 July 16 2020, UPerf
(warmup: 1m, run: 3m)
JDK 11(-28) 物理スレッド
JDK 16-ea5 物理スレッド
JDK 16 Loom+2-14 仮想スレッド
測定条件 Unicast 通信におけるスループット (req/sec)
構成 物理ノード8個によるクラスタ構成
利⽤JDKと
利⽤スレッ
ドの形態
JDK 11 物理スレッド
JDK 16-ea5 物理スレッド
JDK 16 Loom+2-14 仮想スレッド
belaban.blogspot.com/2020/07/double-your-performance-
virtual-threads.html
logico-jp.io/2020/07/27/double-your-performance-virtual-
threads-fibers-and-jdk-15-16/
TCP socketのAPIはすでにJava 13で対応済み
TCP Socket API was already reimplemented in Java 13
ZGC: A Scalable Low-Latency Garbage Collector
Java 15での機能強化
What’s new and enhancement in Java 15
参考資料
malloc.se/blog/zgc-jdk15
logico-jp.io/2020/09/25/zgc-whats-new-in-jdk-15/
Text Blocks
参考資料
cr.openjdk.java.net/~jlaskey/Strings/TextBlocksGuide_v11.html
logico-jp.io/2020/09/09/programmers-guide-to-text-blocks/
Shenandoah: A Low-Pause-Time Garbage Collector
Preview or incubator
プレビューもしくはインキュベート機能
Preview or incubator projects
339 Edwards-Curve Digital Signature Algorithm (EdDSA)
360 Sealed Classes (Preview)
371 Hidden Classes
372 Remove the Nashorn JavaScript Engine
373 Reimplement the Legacy DatagramSocket API
374 Disable and Deprecate Biased Locking
375 Pattern Matching for instanceof (Second Preview)
377 ZGC: A Scalable Low-Latency Garbage Collector
378 Text Blocks
379 Shenandoah: A Low-Pause-Time Garbage Collector
381 Remove the Solaris and SPARC Ports
383 Foreign-Memory Access API (Second Incubator)
384 Records (Second Preview)
385 Deprecate RMI Activation for Removal
Pattern Matching for instanceof (Second Preview)
2種類の instanceof
The operator of “instanceof” works in two ways.
Pattern
openjdk.java.net/jeps/375
ž A pattern is a combination of (1) a predicate that can be applied to a
target, and (2) a set of binding variables that are extracted from the
target only if the predicate successfully applies to it.
ž A type test pattern consists of a predicate that specifies a type,
along with a single binding variable.
obj instanceof String s
(1) (2)
型テストパターン (type test pattern)
これまでは
if (obj instanceof String) {
String s = (String) obj;
// use s
}
このJEP (305, 375) により
if (obj instanceof String s) {
// can use s here
} else {
// can't use s here
}
詳しくはきしださんパートで
Records (Second Preview)
簡単な例
public record Point(int x, int y) {}
public final class Point extends Record {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int x() {
return x;
}
public int y() {
return y;
}
public int hashCode() { ... }
public boolean equals() { ... }
public String toString() { ... }
}
フィールドの名前がそのままAPI
(getXXXではない)
メンバーはfinal
setter (setXXX) は存在しない
Recordの特徴
ž extends できない
public record Point(int x, int y) {}
...
Point p1 = new Point(1, 2);
Point p2 = new Point(1, 2);
Point p3 = new Point(p1.x(), p1.y());
Point p4 = new Point(p1.x(), p2.y());
boolean b1_2 = p1.equals(p2); // true
boolean b1_3 = p1.equals(p3); // true
boolean b3_4 = p3.equals(p4); // true
...
詳しくはきしださんパートで
Sealed Classes (Preview)
public sealed class Shape
permits Circle, Rectangle, Square {...}
例
制限するクラスもしくはインターフェースを宣⾔
拡張許可されたサブクラスが続く
拡張許可されたサブクラスの制約
Limitation of permitted subclasses
Recordと組み合わせることもできる
Able to use Sealed type along with Records
Public sealed interface Expr
permits ConstantExpr, PlusExpr, TimesExpr, NegExpr {...}
public record ConstantExpr(int i) implements Expr {...}
public record PlusExpr(Expr a, Expr b) implements Expr {...}
public record TimesExpr(Expr a, Expr b) implements Expr {...}
public record NegExpr(Expr e) implements Expr {...}
instanceof を使ったパターンマッチング
Pattern matching with instanceof
public sealed class Shape
permits Circle, Rectangle, Square {...}
final class Circle extends Shape {...}
final class Rectangle extends Shape {...}
final class Square extends Shape {...}
Shape rotate(Shape shape, double angle) {
return switch (shape) {
case Circle c -> c; // no-op
case Rectangle r -> r.rotate(angle);
case Square s -> s.rotate(angle);
}
}
詳しくはきしださんパートで
Foreign-Memory Access API (Second Incubator)
ž --add-modules jdk.incubator.foreign
Java 15での強化点
これまで…
Each way to access foreign memory outside of Java heap has pros and cons.
ByteBufferの
direct bufferを使う
直接オフヒープメモリを操作できるが、
• 2GBを超えるdirect bufferは作成できない
• direct bufferに関連付けられたメモリの解放は、ガベージコレ
クタに任されている
Unsafe APIを使う
効率よくアクセスできるが、
• ⽂字通り安全ではない
• Unsafe APIはサポート対象のAPIではない
JNIを使う
理論上は可能だが、
• 偏に⾯倒、⾼コスト
• Javaからネイティブへの移⾏が発⽣するために低速
セグメントとスライス
Segment and Slice
境界と制限 (1) 空間的境界
Spatial boundaries
境界と制限 (2) 時間的境界
Temporal boundaries
境界と制限 (3) スレッド制限
Thread confinements
Thread A
Thread B
VarHandle を使ってセグメント内のメモリにアクセス
Dereference memory segment using VarHandle
// Get a VarHandle for int type
VarHandle intHandle = MemoryHandles.varHandle( int.class,
ByteOrder.nativeOrder());
// Allocate a memory segment (100 bytes), and access it
try (MemorySegment segment = MemorySegment.allocateNative(100)) {
MemoryAddress base = segment.baseAddress();
for (int i = 0; i < 25; i++) {
// Access foreign memory with int type VarHandle
intHandle.set(base.addOffset(i * 4), i);
}
}
セグメントのオーナーシップ – Serial confinement
Segment ownership – Serial confinement
// If segmentA is created in threadA, the segment is confined by threadA
MemorySegment segmentA = ...;
...
// confined by thread B
var segmentB = segmentA.withOwnerThread(threadB);
// shared segment – any threads can access this memory segment.
var segmentB = segmentA.withOwnerThread(null);
セグメントのオーナーシップ - Parallel confinement
Segment ownership - Parallel confinement
// create a memory segment whose size is 1,000,000 × JAVA_INT
SequenceLayout seq = MemoryLayout.ofSequence(1_000_000, MemoryLayouts.JAVA_INT);
SequenceLayout seq_bulk = seq.reshape(-1, 100);
VarHandle intHandle = seq.varHandle(int.class, PathElement.sequenceElement());
// Using spliterator to process memory contents in parallel
int sum = StreamSupport.stream(MemorySegment.spliterator(segment, seq_bulk), true)
.mapToInt(slice -> {
int res = 0;
MemoryAddress base = slice.baseAddress();
for (int i = 0; i < 100 ; i++) {
res += (int)intHandle.get(base, (long)i);
}
return res;
}).sum();
参考資料
cr.openjdk.java.net/~mcimadamore/panama/foreign-memaccess.html
logico-jp.io/2020/08/08/state-of-foreign-memory-support/
Compatibility
Compatibility & Specification Review (CSR)
wiki.openjdk.java.net/display/csr/Main
bugs.openjdk.java.net/issues/?filter=37957
Parallel GC
https://bugs.openjdk.java.net/browse/JDK-8246718
bugs.openjdk.java.net/browse/JDK-8240440
bugs.openjdk.java.net/browse/JDK-8242164
G1 GC
www.phoronix.com/scan.php?page=article&item=openjdk-14-benchmark
SPECjbb 2015でJava 14の性能がJava 8に劣っている...
Why is SPECjbb 2015 result on Java 14 worse than on Java 8?
-XX:MaxRAM=16g だけでHeapを指定しないと...
If only “-XX:MaxRAM=16g” is specified and heap size is not specified...
kstefanj.github.io/2020/04/16/g1-ootb-performance.html
理由
対策
bugs.openjdk.java.net/browse/JDK-8241670
その結果
As a result, ...
kstefanj.github.io/2020/04/16/g1-ootb-performance.html
参考資料
ž JDK 15 G1/Parallel GC changes
tschatzl.github.io/2020/09/01/jdk15-g1-parallel-gc-changes.html
logico-jp.io/2020/09/10/jdk-15-g1-parallel-gc-changes/
kstefanj.github.io/2020/04/16/g1-ootb-performance.html
logico-jp.io/2020/06/18/improving-g1-out-of-the-box-performance/
ž OpenJDK Startup - Late 2019 Edition
cl4es.github.io/2019/11/20/OpenJDK-Startup-Update.html
Takeaways
Java 15
Welcome, Java 15! (Japanese)

Welcome, Java 15! (Japanese)