Slide 1

Slide 1 text

Java 21 Overview Yoshida Shinya (@shinyafox, @bitter_fox) LINE Corporation 2023/09/28

Slide 2

Slide 2 text

Who am I • Senior Serverside Engineer at LINE Corporation • Leader of HBase team for LINE Messenger Backend • Contributed to Java 8, 9 • Project Lambda Contributor • Project Kulla (jshell) Committer • JJUG Board member • Recent work • Modernize Java version for HBase/Hadoop • From Java 8 to Java 17 with new HBase/Hadoop version • Evaluate ZGC for HBase

Slide 3

Slide 3 text

Agenda • Javaの開発とリリース • 最近のJavaリリースの振り返り • Java 21 JEPs • Language • API • JVM&Runtime • Project Loom • Project Panama

Slide 4

Slide 4 text

Javaの開発とリリース • 開発:OpenJDK(OSS Community) hosted on GitHub • https://openjdk.org • https://github.com/openjdk/jdk • 開発課題: Jira, JEP (JDK Enhancement Proposal) • https://bugs.openjdk.org • https://openjdk.org/jeps • 仕様: JSR (Java Specification Request) • Java 21 https://www.jcp.org/en/jsr/detail?id=396 • リリース: 6ヶ月ごと • LTS (Long Term Support) • OpenJDK: LTSバージョンは指定していない • 各ベンダー: どのバージョンを長期的にサポートするか • Oracle: Java 11 (3年) Java 17 (2年) Java 21 (2年) Java 25 ...をLTSに

Slide 5

Slide 5 text

JEP – JDK Enhancement Proposal • PEP: Python Enhancement Proposalを参考にして導入された • Java Platformの大きな新機能、開発、変更の提案 • メタ的な提案 • JEP 1: JDK Enhancement-Proposal & Roadmap Process • JEP 328: Flight Recorder • JEP 110: HTTP/2 Client (Incubator) • JEP 321: HTTP Client • JEP 325: Switch Expressions (Preview) • JEP 354: Switch Expressions (Second Preview) • JEP 361: Switch Expressions • JEP 333: ZGC: A Scalable Low-Latency Garbage Collector (Experimental) • JEP 377: ZGC: A Scalable Low-Latency Garbage Collector (Production)

Slide 6

Slide 6 text

Preview, Incubator, Experimental • 「開発者からのフィードバックが欲しいので試してね」というお試し機能 • 今後のリリースで変更される可能性がある • Preview (JEP 12: Preview Features) • 言語、JVM、APIの新機能 • 完成度: 95% • javac--enable-preview --release 21 && java --enable-preview • Incubator (JEP 11: Incubator Modules) • ある程度大きく、独立した新しいAPI、ツール • 完成度: Previewよりも低い場合がある • jdk.incubatorモジュール • Experimental • JVM実装(HotSpot)の新機能、改善(GC、JITなど) • 完成度: 25% • アプリケーションに支障がある可能性がある • java-XX:+UnlockExperimentalVMOptions

Slide 7

Slide 7 text

2021 2022 2023 2019 2020 2018 9 10 11LTS 14 15 12 13 16 17LTS 18 19 20 21LTS Review Recent Java Releases

Slide 8

Slide 8 text

2021 2022 2023 2019 2020 2018 9 10 11LTS 14 15 12 13 16 17LTS 18 19 20 21LTS Review Recent Java Releases ― Number of JEPs 91 12 17 8 5 17 14 17 14 9 7 7 15

Slide 9

Slide 9 text

2021 2022 2023 2019 2020 2018 9 10 11LTS 14 15 12 13 16 17LTS 18 19 20 21LTS Review Recent Java Releases ― Number of JEPs 91 12 17 8 5 17 14 17 14 9 7 7 15 120 75 38

Slide 10

Slide 10 text

2021 2022 2023 2019 2020 2018 9 10 11LTS 14 15 12 13 16 17LTS 18 19 20 21LTS Review Recent Java Releases ― Key features ・Var ・App CDS ・Var for Lambda ・Epsilon GC ・HTTP Client ・java Main.java ・JFR ・Switch expr ・Helpful NPE ・Remove CMS ・TextBlock ・ZGC ・Shenandoah ・Remove Nashorn ・Record ・Pattern matching for instanceof ・jpackage ・Move to GitHub ・Sealed class ・Remove --illegal-access ・Simple Web Server (jwebserver) ・Jigsaw ・jshell ・New version schema (many)

Slide 11

Slide 11 text

Java 21 JEPs • 430: String Templates (Preview) • 431: Sequenced Collections • 439: Generational ZGC • 440: Record Patterns • 441: Pattern Matching for switch • 442: Foreign Function & Memory API (Third Preview) • 443: Unnamed Patterns and Variables (Preview) • 444: Virtual Threads • 445: Unnamed Classes and Instance Main Methods (Preview) • 446: Scoped Values (Preview) • 448: Vector API (Sixth Incubator) • 449: Deprecate the Windows 32-bit x86 Port for Removal • 451: Prepare to Disallow the Dynamic Loading of Agents • 452: Key Encapsulation Mechanism API • 453: Structured Concurrency (Preview)

Slide 12

Slide 12 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 13

Slide 13 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 14

Slide 14 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 15

Slide 15 text

440: Record Patterns 441: Pattern Matching for switch • Pattern Match • 式(値)を構造と条件によるマッチングを行い値を取り出す言語機能 • どこに書けるか • どんな構造をdeconstructできるか • どんな条件でmachingできるか

Slide 16

Slide 16 text

440: Record Patterns 441: Pattern Matching for switch OK NG どこに書けるか • instanceof expr • Switch condition • Variable definition • Variable in for loop • Method definition どんな構造をdeconstructできるか • Type • Record • Object content • Primitive Type • Array • Collection • j.u.Optional どんな条件でmatchingできるか • Type • Record • Object content • Primitive Type • Enum value • Collections

Slide 17

Slide 17 text

440: Record Patterns 441: Pattern Matching for switch sealed interface Maybe permits Just, Nothing {} record Just(T value) implements Maybe {} record Nothing() implements Maybe {} Maybe> maybe = ...; String str = maybe instanceof Just j ? String.valueOf(j.value()) : "Nothing";

Slide 18

Slide 18 text

440: Record Patterns 441: Pattern Matching for switch sealed interface Maybe permits Just, Nothing {} record Just(T value) implements Maybe {} record Nothing() implements Maybe {} Maybe> maybe = ...; switch (maybe) { case Just j -> // Pattern for Type in switch cond. String.valueOf(j.value()); case Nothing n -> "Nothing"; // Pattern for Type in switch cond. }

Slide 19

Slide 19 text

440: Record Patterns 441: Pattern Matching for switch sealed interface Maybe permits Just, Nothing {} record Just(T value) implements Maybe {} record Nothing() implements Maybe {} Maybe> maybe = ...; switch (maybe) { case Just(var s) -> // Pattern for Record in switch cond. String.valueOf(s); case Nothing() -> "Nothing"; // Pattern for Record in switch cond. }

Slide 20

Slide 20 text

440: Record Patterns 441: Pattern Matching for switch sealed interface Maybe permits Just, Nothing {} record Just(T value) implements Maybe {} record Nothing() implements Maybe {} Maybe> maybe = ...; switch (maybe) { case Just(var s) when s == null -> throw new NullPointerException(); case Just(var s) -> String.valueOf(s); case Nothing n -> "Nothing"; // Pattern for Type in switch cond. case null -> "null" }

Slide 21

Slide 21 text

440: Record Patterns 441: Pattern Matching for switch sealed interface Maybe permits Just, Nothing {} record Just(T value) implements Maybe {} record Nothing() implements Maybe {} Maybe> maybe = ...; switch (maybe) { // Pattern for Record matching Type in switch cond. case Just(String s) -> "String"; case Just(Integer n) -> "Integer"; case Just j -> "Other"; // Pattern for Type in switch cond. case Nothing n -> "Nothing"; // Pattern for Type in switch cond. }

Slide 22

Slide 22 text

440: Record Patterns 441: Pattern Matching for switch sealed interface Maybe permits Just, Nothing {} record Just(T value) implements Maybe {} record Nothing() implements Maybe {} Maybe> maybe = ...; switch (maybe) { // Pattern for Record matching Record in switch cond. case Just(Just(String s)) -> s; case Just(Nothing()) -> "Just Nothing"; case Nothing() -> "Nothing"; }

Slide 23

Slide 23 text

440: Record Patterns 441: Pattern Matching for switch sealed interface FList permits Empty, Cons {} record Empty() implements FList {} record Cons(T head, FList tail) implements FList {} int size(FList> list) { return switch (list) { case Cons(var head, var tail) -> size(tail) + 1; case Empty() -> 0; }; }

Slide 24

Slide 24 text

440: Record Patterns 441: Pattern Matching for switch enum Action { SHRINK, EXPAND } Maybe action = ...; size += switch (action) { case Just(SHRINK) -> -10; // NG, cannot match with Enum value case Just(EXPAND) -> 10; // NG, cannot match with Enum value case Nothing() -> 0; }

Slide 25

Slide 25 text

440: Record Patterns 441: Pattern Matching for switch enum Action { SHRINK, EXPAND } Maybe action = ...; size += switch (action) { case Just(var a) when a == Action.SHRINK -> -10; case Just(var a) when a == Action.EXPAND -> 10; case Just j -> throw new ISE("Added new enum value to Action"); case Nothing() -> 0; }

Slide 26

Slide 26 text

440: Record Patterns 441: Pattern Matching for switch enum Action { SHRINK, EXPAND } Maybe action = ...; size += switch (action) { case Just(var a) -> switch (a) { case SHRINK -> -10; case EXPAND -> 10; }; case Nothing() -> 0; }

Slide 27

Slide 27 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 28

Slide 28 text

430: String Templates • 文字列リテラル内に記載されたその言語の式を評価し、文字列等を作る構文 • Scala: s"$x plus $y equals ${x + y}" • Kotlin: "$x plus $y equals ${x + y}" • C#: $"{x} plus {y} equals {x + y}" • Ruby: "#{x} plus #{y} equals #{x + y}" • Python: f"{x} plus {y} equals {x + y}" • 各言語の違い • 通常の文字列リテラルと区別するか • 文字列内の式を区別する文字 • 検証や文字列以外への変換をユーザ定義できるか (Scala)

Slide 29

Slide 29 text

430: String Templates • String Templatesは危険? • 一般にどんな言語機能も良くない使い方ができてしまう • 便利であればあるほど、うっかりやってしまう • var query = "SELECT * FROM users WHERE uname = '$uname'" • JSON object、Regex object、SQL objectなどに変換できたら便利で安全 • →検証や文字列以外への変換をユーザ定義できるか • Scala • そしてJavaも

Slide 30

Slide 30 text

430: String Templates • String s = STR."\{x} plus \{y} equals \{x + y}" • String Template内の式を区別する文字: ¥{...} • ¥{は既存の文字列リテラルでは使われていない • "¥¥{" • $,#は使われている • 通常の文字列リテラルで¥{x}を書くとエラー • 検証や文字列以外への変換をユーザ定義できる • StringTemplate + StringTemplate.Processor

Slide 31

Slide 31 text

430: String Templates •StringTemplateリテラルとStringTemplate.Processorを組み合わせて使う STR."\{x} plus \{y} equals \{x + y}" •StringTemplate.STR: StringTemplate.Processor •"\{x} plus \{y} equals \{x + y}" StringTemplate.of( fragments = List.of(""," plus "," equals ", "") values = List.of( x, y, x + y) ) •StringTemplate.STR.process(StringTemplate.of(...)) •bytecodeレベルではindyを使って最適化している

Slide 32

Slide 32 text

430: String Templates • StringTemplate.Processorは各々で定義できる • R process(StringTemplate st) throws E; • R: 文字列テンプレート式の値の型 • E: 文字列テンプレート式によって発生する例外 • stの検証と値の変換のみに注力するべき • DBアクセスなどはオススメされない • 例 • StringTemplate.RAW: StringTemplate.Processor • FormatProcessor.FMT • LocalizationProcessor(Locale locale) • JSON: StringTemplate.Processor • SQL: StringTemplate.Processor • C: StringTemplate.Processor, CNFException>

Slide 33

Slide 33 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 34

Slide 34 text

443: Unnamed Patterns and Variables (Preview) • 不必要な宣言を_で代用できる • パターン • 変数 • try-with-resources • for-loop • catchした例外 • ラムダのパラメーター try (var _ = newTracer()) { if (getEntity(id) instanceof Entity(_, var kind)) { // Entity(var _, var kind)もOK map.computeIfAbsent(kind, _ -> new ArrayList<>()) .add(id); } } catch (IOE _) {}

Slide 35

Slide 35 text

445: Unnamed Classes and Instance Main Methods (Preview) $ cat Main.java import static java.lang.System.*; final String NAME = "Java"; // static void sayHello() { Util.print(STR."Hello \{NAME}"); // Main.Util.print(...)もOK } void main() { // String... argsは省略可 (クラス内に宣言した場合も) sayHello(); } class Util { // Main.Util static void print(String msg) { out.println(msg); } } $ javac … Main.java $ ls *.class Main.class Main$Util.class

Slide 36

Slide 36 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 37

Slide 37 text

431: Sequenced Collections • List • LinkedHashSet • SortedSet • NavigableSet • TreeSet • Deque • BlockingDeque • LinkedHashMap • SortedMap • NavigableMap • TreeMap

Slide 38

Slide 38 text

431: Sequenced Collections • List • LinkedHashSet • SortedSet • NavigableSet • TreeSet • Deque • BlockingDeque • LinkedHashMap • SortedMap • NavigableMap • TreeMap • 先頭の要素 • 末尾の要素

Slide 39

Slide 39 text

431: Sequenced Collections • List: get(0), get(size()-1) • LinkedHashSet • SortedSet: first(), last() • NavigableSet: first(), last(), pollFirst(), pollLast() • TreeSet • Deque: getFirst(), getLast() • BlockingDeque • LinkedHashMap • SortedMap: firstKey(), lastKey() • NavigableMap: firstEntry(), lastEntry(), pollFirstEntry(), pollLastEntry() • TreeMap • 先頭の要素 • 末尾の要素

Slide 40

Slide 40 text

431: Sequenced Collections • SequencedCollection extends Collection • E getFirst() • E getLast() • void addFirst(E) throws USE • void addLast(E) throws USE • E removeFirst(E) throws USE • E removeLast(E) throws USE • SequencedCollection reversed() • SequencedSet extends Set, SequenecdCollection • SequencedSet reversed() • SequencedMap extends Map • Entry firstEntry() • Entry lastEntry() • void putFirstEntry(Entry) throws USE • void putLastEntry(Etnry) throws USE • Entry pollFirstEntry() throws USE • Entry pollLastEntry() throws USE • SequencedMap reversed() • SequencedSet> sequencedEntrySet() • SequencedSet sequencedKeySet() • SequencedCollection sequencedValues()

Slide 41

Slide 41 text

431: Sequenced Collections • SequencedCollection extends Collection • E getFirst() • E getLast() • void addFirst(E) throws USE • void addLast(E) throws USE • E removeFirst(E) throws USE • E removeLast(E) throws USE • SequencedCollection reversed() • SequencedSet extends Set, SequenecdCollection • SequencedSet reversed() • SequencedMap extends Map • Entry firstEntry() • Entry lastEntry() • void putFirstEntry(Entry) throws USE • void putLastEntry(Etnry) throws USE • Entry pollFirstEntry() throws USE • Entry pollLastEntry() throws USE • SequencedMap reversed() • SequencedSet> sequencedEntrySet() • SequencedSet sequencedKeySet() • SequencedCollection sequencedValues()

Slide 42

Slide 42 text

431: Sequenced Collections • SequencedCollection extends Collection • E getFirst() • E getLast() • void addFirst(E) throws USE • void addLast(E) throws USE • E removeFirst(E) throws USE • E removeLast(E) throws USE • SequencedCollection reversed() • SequencedSet extends Set, SequenecdCollection • SequencedSet reversed() • SequencedMap extends Map • Entry firstEntry() • Entry lastEntry() • void putFirstEntry(Entry) throws USE • void putLastEntry(Etnry) throws USE • Entry pollFirstEntry() throws USE • Entry pollLastEntry() throws USE • SequencedMap reversed() • SequencedSet> sequencedEntrySet() • SequencedSet sequencedKeySet() • SequencedCollection sequencedValues()

Slide 43

Slide 43 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 44

Slide 44 text

452: Key Encapsulation Mechanism API • 鍵カプセル化メカニズム(KEM; Key Encapslation Mechanism)をJava APIに • ハイブリッド暗号のための仕様、暗号化方式 • 公開鍵暗号: 安全に鍵交換が可能、性能が課題 • 共通鍵暗号: 性能は良い、鍵交換が課題 • ハイブリッド暗号:公開鍵暗号を用い共通鍵を共有し、平文を共通鍵で暗号化する • 耐量子暗号ではKEMが標準的に • NISTは公募する耐量子暗号にKEMを求めている • CRYSTALS-Kyber

Slide 45

Slide 45 text

452: Key Encapsulation Mechanism API ※ABC, ABC-KEMはアルゴリズム名 (RSA, RSA-KEM)など OpenJDKではDHKEM (ディフィー・ヘルマン鍵共有)がサポートされている // Alice KEM kemR = KEM.getInstance("ABC-KEM"); var g = KeyPairGenerator.getInstance("ABC"); var kp = g.generateKeyPair(); publishKey(kp.getPublic()); var em = receiveBytes(); var params = receiveBytes(); var algParams = AlgorithmParameters.getInstance("ABC-KEM"); algParams.init(params); var spec = algParams.getParameterSpec(ABCKEMParameterSpec.class); KEM.Decapsulator d = kem.newDecapsulator(kp.getPrivate(), spec); SecretKey key = d.decapsulate(em); // Bob KEM kem = KEM.getInstance("ABC-KEM"); PublicKey pk = retrieveKey(); var spec = new ABCKEMParameterSpec(...); KEM.Encapsulator e = kem.newEncapsulator(pk, spec, null); KEM.Encapsulated enc = e.encapsulate(); sendBytes(enc.encapsulation()); sendBytes(enc.params()); SecretKey key = enc.key();

Slide 46

Slide 46 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 47

Slide 47 text

451: Prepare to Disallow the Dynamic Loading of Agents • Java Agent (Java 5) • 実行時に動的にクラスの挙動を変更できる • 起動時に--javaagent--agentlibで明示的に指定 • 無害なモニタリングなどの用途で導入された • アスペクト指向やJDKの挙動を変えるのに使いだされた • Attach API (Java 6) • 実行中のJavaプロセスに接続して監視などを行える • Java Agentを動的にロードできてしまう • Jigsaw (Java 9) • JDKやライブラリに強力なカプセル化を導入 • Java Agentを使ってそれを迂回できてしまう

Slide 48

Slide 48 text

451: Prepare to Disallow the Dynamic Loading of Agents • Attach APIを使ってJava Agentを動的にロードすると警告 • 将来的にはデフォルトでは禁止に • --javaagentで静的にロード:OK • 動的にロードする場合:-XX:+EnableDynamicAgentLoading • Java AgentをロードしないAttachAPIを使用するツール:影響を受けない • jcmd • jconsole • ... WARNING: A {Java,JVM TI} agent has been loaded dynamically (file:/u/bob/agent.jar) WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information WARNING: Dynamic loading of agents will be disallowed by default in a future release

Slide 49

Slide 49 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 50

Slide 50 text

449: Deprecate the Windows 32-bit x86 Port for Removal • Windows 10 • 32 bit arch.をサポートする最後のWindows • 2025/10/14サポート終了予定 • Windows 32-bit x86向けのJDKのサポートを将来終了するための準備

Slide 51

Slide 51 text

Java 21 JEPs • Language (Project Amber, etc) • 440: Record Patterns • 441: Pattern Matching for switch • 430: String Templates (Preview) • 443: Unnamed Patterns and Variables (Preview) • 445: Unnamed Classes and Instance Main Methods (Preview) • API • 431: Sequenced Collections • 452: Key Encapsulation Mechanism API • JVM&Runtime • 439: Generational ZGC • 451: Prepare to Disallow the Dynamic Loading of Agents • 449: Deprecate the Windows 32-bit x86 Port for Removal • Project Loom • 444: Virtual Threads • 446: Scoped Values (Preview) • 453: Structured Concurrency (Preview) • Project Panama • 442: Foreign Function & Memory API (Third Preview) • 448: Vector API (Sixth Incubator)

Slide 52

Slide 52 text

Project Loom • Virtual Threads + 限定継続をJavaに導入 • IO待ちの多い同期処理をスケーラブルに並列実行可能 • マルチスレッドに関連した処理を簡潔、明瞭に行えるよう改良 • 446: Scoped Values (Preview) • Thread Local VariableのPainpointsを改良 • 453: Structured Concurrency (Preview) • 並列実行した処理の結果待ちを簡単に

Slide 53

Slide 53 text

DB DB DB DB 512 threads / App 50%tile latency = 10ms request = 5000 rps / App LB LB App App App App

Slide 54

Slide 54 text

DB DB DB DB 512 threads / App 50%tile latency = 10ms request = 5000 rps / App LB LB App App App App

Slide 55

Slide 55 text

Metrics (平常時)

Slide 56

Slide 56 text

DB DB DB DB 512 threads / App 50%tile latency = 10ms request = 5000 rps / App LB LB App App App App

Slide 57

Slide 57 text

DB DB DB DB 512 threads / App 50%tile latency = 10ms request = 5000 rps / App LB LB App App App App DB failure!! 95%tile latency = 3000ms

Slide 58

Slide 58 text

Metrics (95%tile悪化時)

Slide 59

Slide 59 text

Java Thread = OS Thread Thread 1 Thread 2 Thread 3 validate DB access unpack response validate DB access unpack response validate DB access unpack response validate DB access unpack response validate DB access unpack response validate DB access unpack response Queue

Slide 60

Slide 60 text

Thread 2 Thread 3 validate DB access unpack response validate DB access unpack response validate DB access unpack response validate DB access 3s unpack response validate DB access unpack response validate DB access 3s unpack response validate DB validate DB access unpack response validate DB access unpack response validate DB access 3s Queue 10msで終わるのに もう1秒も待ってる Java Thread = OS Thread Thread 1

Slide 61

Slide 61 text

IO Event handler thread validate validate validate Application thread unpack response unpack response unpack response Application thread IO Event handler loop DB request + callback Run callback DB request + callback Run callback DB request + callback Run callback DB DB DB validate DB request + callback DB unpack response

Slide 62

Slide 62 text

Non blocking IOと非同期処理のPainpoints • JavaだとCallback hell • ラムダ式、メソッドチェーン • try-catchとの相性が最悪 • IOを呼び出したスレッドと違うスレッドで後続の処理 • スレッドセーフティ • プログラムの挙動がわかりにくく、調査やデバッグが難しい • Stack traceなど • (キャッシュ効率↓) • 慣れればそんなに辛くはないが、それでも同期処理よりは難しい

Slide 63

Slide 63 text

Thread 2 Thread 3 validate DB access unpack response validate DB access Virtual Thread Thread 1 Java Thread = OS Thread Carrier Thread DB access 3s validate DB done? or yield() validate DB done? or yield() unpack response unpack response validate DB access unpack response validate DB done? or yield() DB done? or yield() unpack response unpack response

Slide 64

Slide 64 text

Metrics (95%tile悪化時 + Virtual Thread)

Slide 65

Slide 65 text

Metrics (95%tile悪化時, Before/After)

Slide 66

Slide 66 text

Metrics (95%tile悪化時, Before/After)

Slide 67

Slide 67 text

Platform ThreadとVirtual Thread CPU 1 CPU 2 CPU 3 CPU 4 Platform Thread Platform Thread Platform Thread Platform Thread OS OS Thread OS Thread OS Thread OS Thread Java Runtime Java application Carrier Threads ForkJoinPool Virtual Thread Virtual Thread

Slide 68

Slide 68 text

Virtual Thread • 任意のCarrier Threadで実行される • yield or 終了するまでCarrier Threadを専有する • タイムシェアリングは行われない • Thread.startVirtualThread(Runnable): void • Thread.ofVirtual() • .factory(): ThreadFactory • .start(Runnable): Thread • .unstarted(Runnable): Thread • Executors.newVirtualThreadPerTaskExecutor(): ExecutorService • Tomcat • org.apache.catalina.core.StandardVirtualThreadExecutor

Slide 69

Slide 69 text

yield • 処理を中断して、Carrier Threadの専有を解く • 明示的に呼び出す必要がある • 基本的にはライブラリが呼び出している • sleep, await, lock, File IO, Socket IO, NIO, ... • 限定継続のreset • shiftはJava (Virtual Thread scheduler)が呼び出す • Thread.yield()

Slide 70

Slide 70 text

Virtual Threadの設定 (System property) • jdk.virtualThreadScheduler.parallelism • 基準となる並列度 (Carrier Thread数) • Default: Runtime.getRuntime().availableProcessors() • jdk.virtualThreadScheduler.maxPoolSize • プールされる最大のCarrier Thread数 • Default: max(parallelism, 256) • Carrier Threadがブロックされたときに、Carrier Threadを増やせる? • 挙動を確認できず • jdk.virtualThreadScheduler.minRunnable • 最小のCarrierThread数 • Default: max(parallelism / 2, 1)

Slide 71

Slide 71 text

Virtual Threadがあれば非同期処理は不要? • VT+同期処理、非同期処理を組み合わせることが重要 • 非同期処理: 低レスポンスタイム Thread.startVirtualThread(() -> { var aFuture = readFromDB1(); var bFuture = readFromDB2(); var cFuture = readFromMicroservice(); var a = aFuture.get(); // ... }); • → JEP 453: Structured Concurrency

Slide 72

Slide 72 text

Virtual Threadの注意点 • Virtual Threadをプールしない • yieldを行わない処理を長時間実行しない • Carrier Threadを専有して他のVTの実行を阻害 • Platform Threadで実行してawait • Thread.yield()を呼ぶ • 長時間のsynchronized、Object.wait()、nativeメソッド • yieldを行わない • レイテンシが上がる可能性 • アプリケーションのシャットダウンに注意 • Virtual Threadはdaemon thread • Carrier ThreadのExecutorを変更できない • モニタリング、リソースの分離、schedulingのカスタマイズできない • リフレクションを使えば変更可能 • jstackではVTのスタックトレースを取得できない • jcmd Thread.dump_to_file -format=json

Slide 73

Slide 73 text

Java 21まとめ • Pattern Matchingは着実に進歩 • その他のPreview言語機能もいい感じ • ついにVirtualThreadがGA • Thread、ExecutorServiceから扱えるので既存の資産を再利用できる • 注意点が多いのでプロダクション適用時は要確認 • Java 22は2024/03/19リリース予定 • まだまだ進化するJava、今すぐダウンロー ド!

Slide 74

Slide 74 text

おまけ void startSendRequests() { var executor = newFixedThreadPool(500); for (int i = 0; i < 500; i++) { executor.submit(() -> { while (true) { handleRequest(); try { Thread.sleep(100); } catch (InterruptedException _) {} } }); } } ExecutorService serverThreads = newFixedThreadPool(512); ExecutorService serverThreads = newVirtualThreadPerTaskExecutor(); void handleRequest() { queueSize.incrementAndGet(); long startNano = System.nanoTime(); serverThreads.submit(() -> { queueSize.decrementAndGet(); activeThreads.incrementAndGet(); accessToDB(); long endNano = System.nanoTime(); totalResponseTime.getAndAdd(endNano - startNano); responseTimes.add(endNano - startNano); activeThreads.decrementAndGet(); requestCount.incrementAndGet(); return null; }); } void accessToDB() { boolean dbSuccess = !databaseFailure || ThreadLocalRandom.current().nextDouble() < 0.95; try { if (dbSuccess) { Thread.sleep(10); } else { Thread.sleep(3_000); } } catch (InterruptedException _) {} }

Slide 75

Slide 75 text

void main() { for (int t = 0; t < 100; t++) { int id = t; runCountPrimeNumberAsVirtualThread(id, false); // runCountPrimeNumberAsVirtualThread(id, true); // runCountPrimeNumber2AsPlatformThreadFromVirtualThread(id); long startFasterIO = System.nanoTime(); Thread.startVirtualThread(() -> { System.out.println(STR."Faster IO (\{100+id})"); try { Thread.sleep(100); } catch (Exception _) {} long endFasterIO = System.nanoTime(); long duration = TimeUnit.NANOSECONDS.toMillis(end - start); System.out.println(STR."Faster IO (\{100+id}): \{duration}ms"); }); } // await jobs } void runCountPrimeNumberAsVirtualThread(int id, boolean yield) { long start = System.nanoTime(); Thread.startVirtualThread(() -> { int target = ThreadLocalRandom.current().nextInt(500_000); println(STR."COMP (\{id}): 2~\{target}"); int count = countPrimeNumber(target, yield); long end = System.nanoTime(); long duration = TimeUnit.NANOSECONDS.toMillis(end - start); println(STR."COMP (\{id}): \{duration}ms"); }); } ExecutorService e = Executors.newFixedThreadPool(100); void runCountPrimeNumber2AsPlatformThreadFromVirtualThread(int id) { long start = System.nanoTime(); Thread.startVirtualThread(() -> { int target = ThreadLocalRandom.current().nextInt(500_000); println(STR."COMP (\{id}): 2~\{target}"); try { int count = e.submit(() -> countPrimeNumber(target, false)).get(); long end = System.nanoTime(); long duration = TimeUnit.NANOSECONDS.toMillis(end - start); println(STR."COMP (\{id}): \{duration}ms"); } catch (Exception _) {} }); } int countPrimeNumber(int target, boolean yield) { int count = 0; outer: for (int i = 2; i <= target; i++) { // Intentionally slow implementation for (int j = 2; j < i; j++) { if (i % j == 0) { continue outer; } } count++; if (yield) { Thread.yield(); } } return count; }