Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Java 21 Overview

Java 21 Overview

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

LINE Developers

September 28, 2023
Tweet

More Decks by LINE Developers

Other Decks in Technology

Transcript

  1. 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
  2. Agenda • Javaの開発とリリース • 最近のJavaリリースの振り返り • Java 21 JEPs •

    Language • API • JVM&Runtime • Project Loom • Project Panama
  3. 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に
  4. 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)
  5. 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
  6. 2021 2022 2023 2019 2020 2018 9 10 11LTS 14

    15 12 13 16 17LTS 18 19 20 21LTS Review Recent Java Releases
  7. 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
  8. 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
  9. 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)
  10. 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)
  11. 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)
  12. 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)
  13. 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)
  14. 440: Record Patterns 441: Pattern Matching for switch • Pattern

    Match • 式(値)を構造と条件によるマッチングを行い値を取り出す言語機能 • どこに書けるか • どんな構造をdeconstructできるか • どんな条件でmachingできるか
  15. 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
  16. 440: Record Patterns 441: Pattern Matching for switch sealed interface

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

    Maybe<T> permits Just, Nothing {} record Just<T>(T value) implements Maybe<T> {} record Nothing<T>() implements Maybe<T> {} 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. }
  18. 440: Record Patterns 441: Pattern Matching for switch sealed interface

    Maybe<T> permits Just, Nothing {} record Just<T>(T value) implements Maybe<T> {} record Nothing<T>() implements Maybe<T> {} 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. }
  19. 440: Record Patterns 441: Pattern Matching for switch sealed interface

    Maybe<T> permits Just, Nothing {} record Just<T>(T value) implements Maybe<T> {} record Nothing<T>() implements Maybe<T> {} 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" }
  20. 440: Record Patterns 441: Pattern Matching for switch sealed interface

    Maybe<T> permits Just, Nothing {} record Just<T>(T value) implements Maybe<T> {} record Nothing<T>() implements Maybe<T> {} 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. }
  21. 440: Record Patterns 441: Pattern Matching for switch sealed interface

    Maybe<T> permits Just, Nothing {} record Just<T>(T value) implements Maybe<T> {} record Nothing<T>() implements Maybe<T> {} Maybe<Maybe<String>> 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"; }
  22. 440: Record Patterns 441: Pattern Matching for switch sealed interface

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

    { SHRINK, EXPAND } Maybe<Action> 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; }
  24. 440: Record Patterns 441: Pattern Matching for switch enum Action

    { SHRINK, EXPAND } Maybe<Action> 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; }
  25. 440: Record Patterns 441: Pattern Matching for switch enum Action

    { SHRINK, EXPAND } Maybe<Action> action = ...; size += switch (action) { case Just(var a) -> switch (a) { case SHRINK -> -10; case EXPAND -> 10; }; case Nothing() -> 0; }
  26. 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)
  27. 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)
  28. 430: String Templates • String Templatesは危険? • 一般にどんな言語機能も良くない使い方ができてしまう • 便利であればあるほど、うっかりやってしまう

    • var query = "SELECT * FROM users WHERE uname = '$uname'" • JSON object、Regex object、SQL objectなどに変換できたら便利で安全 • →検証や文字列以外への変換をユーザ定義できるか • Scala • そしてJavaも
  29. 430: String Templates • String s = STR."\{x} plus \{y}

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

    y}" •StringTemplate.STR: StringTemplate.Processor<String, j.l.RException> •"\{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を使って最適化している
  31. 430: String Templates • StringTemplate.Processor<R, E>は各々で定義できる • R process(StringTemplate st)

    throws E; • R: 文字列テンプレート式の値の型 • E: 文字列テンプレート式によって発生する例外 • stの検証と値の変換のみに注力するべき • DBアクセスなどはオススメされない • 例 • StringTemplate.RAW: StringTemplate.Processor<StringTemplate, ...> • FormatProcessor.FMT • LocalizationProcessor(Locale locale) • JSON: StringTemplate.Processor<JSONObject, ...> • SQL: StringTemplate.Processor<PreparedStatement, ...> • C: StringTemplate.Processor<Class<?>, CNFException>
  32. 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)
  33. 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 _) {}
  34. 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
  35. 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)
  36. 431: Sequenced Collections • List • LinkedHashSet • SortedSet •

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

    NavigableSet • TreeSet • Deque • BlockingDeque • LinkedHashMap • SortedMap • NavigableMap • TreeMap • 先頭の要素 • 末尾の要素
  38. 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 • 先頭の要素 • 末尾の要素
  39. 431: Sequenced Collections • SequencedCollection<E> extends Collection<E> • 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<E> reversed() • SequencedSet<E> extends Set<E>, SequenecdCollection<E> • SequencedSet<E> reversed() • SequencedMap<K, V> extends Map<K, V> • Entry<K, V> firstEntry() • Entry<K, V> lastEntry() • void putFirstEntry(Entry<K, V>) throws USE • void putLastEntry(Etnry<K, V>) throws USE • Entry<K, V> pollFirstEntry() throws USE • Entry<K, V> pollLastEntry() throws USE • SequencedMap<K, V> reversed() • SequencedSet<Entry<K, V>> sequencedEntrySet() • SequencedSet<K> sequencedKeySet() • SequencedCollection<V> sequencedValues()
  40. 431: Sequenced Collections • SequencedCollection<E> extends Collection<E> • 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<E> reversed() • SequencedSet<E> extends Set<E>, SequenecdCollection<E> • SequencedSet<E> reversed() • SequencedMap<K, V> extends Map<K, V> • Entry<K, V> firstEntry() • Entry<K, V> lastEntry() • void putFirstEntry(Entry<K, V>) throws USE • void putLastEntry(Etnry<K, V>) throws USE • Entry<K, V> pollFirstEntry() throws USE • Entry<K, V> pollLastEntry() throws USE • SequencedMap<K, V> reversed() • SequencedSet<Entry<K, V>> sequencedEntrySet() • SequencedSet<K> sequencedKeySet() • SequencedCollection<V> sequencedValues()
  41. 431: Sequenced Collections • SequencedCollection<E> extends Collection<E> • 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<E> reversed() • SequencedSet<E> extends Set<E>, SequenecdCollection<E> • SequencedSet<E> reversed() • SequencedMap<K, V> extends Map<K, V> • Entry<K, V> firstEntry() • Entry<K, V> lastEntry() • void putFirstEntry(Entry<K, V>) throws USE • void putLastEntry(Etnry<K, V>) throws USE • Entry<K, V> pollFirstEntry() throws USE • Entry<K, V> pollLastEntry() throws USE • SequencedMap<K, V> reversed() • SequencedSet<Entry<K, V>> sequencedEntrySet() • SequencedSet<K> sequencedKeySet() • SequencedCollection<V> sequencedValues()
  42. 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)
  43. 452: Key Encapsulation Mechanism API • 鍵カプセル化メカニズム(KEM; Key Encapslation Mechanism)をJava

    APIに • ハイブリッド暗号のための仕様、暗号化方式 • 公開鍵暗号: 安全に鍵交換が可能、性能が課題 • 共通鍵暗号: 性能は良い、鍵交換が課題 • ハイブリッド暗号:公開鍵暗号を用い共通鍵を共有し、平文を共通鍵で暗号化する • 耐量子暗号ではKEMが標準的に • NISTは公募する耐量子暗号にKEMを求めている • CRYSTALS-Kyber
  44. 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();
  45. 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)
  46. 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を使ってそれを迂回できてしまう
  47. 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
  48. 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)
  49. 449: Deprecate the Windows 32-bit x86 Port for Removal •

    Windows 10 • 32 bit arch.をサポートする最後のWindows • 2025/10/14サポート終了予定 • Windows 32-bit x86向けのJDKのサポートを将来終了するための準備
  50. 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)
  51. Project Loom • Virtual Threads + 限定継続をJavaに導入 • IO待ちの多い同期処理をスケーラブルに並列実行可能 •

    マルチスレッドに関連した処理を簡潔、明瞭に行えるよう改良 • 446: Scoped Values (Preview) • Thread Local VariableのPainpointsを改良 • 453: Structured Concurrency (Preview) • 並列実行した処理の結果待ちを簡単に
  52. DB DB DB DB 512 threads / App 50%tile latency

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

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

    = 10ms request = 5000 rps / App LB LB App App App App
  55. 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
  56. 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
  57. 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
  58. 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
  59. Non blocking IOと非同期処理のPainpoints • JavaだとCallback hell • ラムダ式、メソッドチェーン • try-catchとの相性が最悪

    • IOを呼び出したスレッドと違うスレッドで後続の処理 • スレッドセーフティ • プログラムの挙動がわかりにくく、調査やデバッグが難しい • Stack traceなど • (キャッシュ効率↓) • 慣れればそんなに辛くはないが、それでも同期処理よりは難しい
  60. 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
  61. 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
  62. 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
  63. yield • 処理を中断して、Carrier Threadの専有を解く • 明示的に呼び出す必要がある • 基本的にはライブラリが呼び出している • sleep,

    await, lock, File IO, Socket IO, NIO, ... • 限定継続のreset • shiftはJava (Virtual Thread scheduler)が呼び出す • Thread.yield()
  64. 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)
  65. Virtual Threadがあれば非同期処理は不要? • VT+同期処理、非同期処理を組み合わせることが重要 • 非同期処理: 低レスポンスタイム Thread.startVirtualThread(() -> {

    var aFuture = readFromDB1(); var bFuture = readFromDB2(); var cFuture = readFromMicroservice(); var a = aFuture.get(); // ... }); • → JEP 453: Structured Concurrency
  66. 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 <pid> Thread.dump_to_file -format=json <path>
  67. Java 21まとめ • Pattern Matchingは着実に進歩 • その他のPreview言語機能もいい感じ • ついにVirtualThreadがGA •

    Thread、ExecutorServiceから扱えるので既存の資産を再利用できる • 注意点が多いのでプロダクション適用時は要確認 • Java 22は2024/03/19リリース予定 • まだまだ進化するJava、今すぐダウンロー ド!
  68. おまけ 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 _) {} }
  69. 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; }