Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Javaの新機能を軽く / Breaf introduction of Java 14

Javaの新機能を軽く / Breaf introduction of Java 14

2020/5/22に開催されたJJUGイベントでの登壇資料です。

Naoki Kishida

May 22, 2020
Tweet

More Decks by Naoki Kishida

Other Decks in Programming

Transcript

  1. Java14新機能を軽く
    2020/5/23 Java生誕25周年 記念イベント
    LINE Fukuoka きしだ なおき

    View Slide

  2. 自己紹介
    • きしだ なおき
    • LINE Fukuoka
    • @kis
    • https://nowokay.hatenablog.com/

    View Slide

  3. タイトル画像について
    • ストックホルム宮殿
    • カール14世ヨハン元国王の像
    • 2020/2/2 JFokusで撮影
    wikimediaより

    View Slide

  4. chiroitoによる再現

    View Slide

  5. Java 14がリリースされてますね
    • 3/17にリリース
    • 16 JEPs
    • 主な新機能はJEPとして
    まとめられている
    • non LTS
    • パッチはJava15が出るまで
    • 現在は14.0.1がリリース
    • 7月の14.0.2まで
    • 次のLTSは17(2021年9月)

    View Slide

  6. Java 14の機能
    • 言語
    • Records(preview)
    • Pattern Matching(preview)
    • Text Blocks(preview 2)
    • Switch Expression(standard)
    • GC
    • ZGC: supports Windows/Mac
    • G1:NUMA aware memory alloc
    • CMS: Removed
    • ParallelGC: Deprecate useless
    option
    (Parallel Young gen+Serial Old)
    • ライブラリ
    • Helpful NullPointerException
    • JFR event streaming
    • Foreign Memory
    Access(Incubator)
    • Non-volatile mapped byte buffer
    • ツール
    • Packaging Tool(Incubator)
    • Remove Pack200
    • JDK
    • Deprecate Solaris/SPARC

    View Slide

  7. Java 14の機能
    • 言語
    • Records(preview)
    • Pattern Matching(preview)
    • Text Blocks(preview 2)
    • Switch Expression(standard)
    • GC
    • ZGC: supports Windows/Mac
    • G1:NUMA aware memory alloc
    • CMS: Removed
    • ParallelGC: Deprecate useless
    option
    (Parallel Young gen+Serial Old)
    • ライブラリ
    • Helpful NullPointerException
    • JFR event streaming
    • Foreign Memory
    Access(Incubator)
    • Non-volatile mapped byte buffer
    • ツール
    • Packaging Tool(Incubator)
    • Remove Pack200
    • JDK
    • Deprecate Solaris/SPARC

    View Slide

  8. ところで試用機能について
    • 試用機能
    • JDKリリースに含まれることで手軽に試せて、多くのフィードバックができる
    • Preview
    • 言語機能
    • `--enable-preview` がjava / javac コマンドに必要
    • 3段階で標準化
    • preview: Records, Pattern Matching for instanceof
    • preview 2(小変更が入る): Text Blocks
    • standard(変更は入らない): Switch Expression
    • Incubator
    • ライブラリ
    • incubatorモジュールのインポートが必要
    • Experimental
    • JVM機能(GC, JIT)
    • -XX:+UnlockExperimentalVMOptions
    • 正式化するときは‘Production’(standardではない)

    View Slide

  9. 言語機能
    • Text Blocks(Preview2)
    • Switch expression(Standard)
    • Records(Preview)
    • Pattern matching for instanceof(Preview)

    View Slide

  10. 言語機能
    • Text Blocks(Preview2)
    • Switch expression(Standard)
    • Records(Preview)
    • Pattern matching for instanceof(Preview)

    View Slide

  11. Text Blocks(Preview 2)
    • 複数行のテキスト
    • ダブルクオート3つで囲む
    • Raw Stringsとして12で導入されかけたけどバッククオートが
    もったいないとして取り下げ
    • Text BlocksとしてJava 13でPreviewとして入った。15で
    Standardになる予定(JEP 378)
    """

    Java 14

    """

    View Slide

  12. ルール
    """

    Java 14

    """
    ダブルクオート3つは内容の文字列とは独立した行に
    右端のスペースは無視される

    View Slide

  13. var s = """

    Java 14

    """;
    var s = """

    Java 14

    """;
    var s = """

    Java 14

    """;
    インデント
    • 一番ひだりにあわせられる
    ``の位置が基準
    閉じ側の`"""`の位置が基準
    ``の位置が基準

    View Slide

  14. エスケープ
    • 14でのPreview2で入った
    • 改行のエスケープ(¥)
    • スペース文字(¥s)
    • 行末のスペースは無視される
    • 行末にスペースが欲しいときは ‘¥s’を入れる
    var s = """
    Lorem ipsum dolor ¥
    sit amet consectetur ¥s
    """;
    var s = "Lorem ipsum dolor sit amet consectetur ";

    View Slide

  15. 言語機能
    • Text Blocks(Preview2)
    • Switch expression(Standard)
    • Records(Preview)
    • Pattern matching for instanceof(Preview)

    View Slide

  16. Switch expression(Standard)
    • Switchがステートメントとしてだけではなく式として使える
    • 最初にJava 12でPreviewとして導入された
    • Java 13で少し変更が入りPreview 2になりそのまま標準化
    int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY -> 7;
    case THURSDAY, SATURDAY -> 8;
    case WEDNESDAY -> 9;
    }

    View Slide

  17. 複数のcaseラベル
    • case句に複数のラベルを指定できるようになった
    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;
    };
    switch (day) {
    case MONDAY, FRIDAY, SUNDAY:
    numLetters = 6;
    break;
    case TUESDAY:
    numLetters = 7;
    break;
    case THURSDAY, SATURDAY:
    numLetters = 8;
    break;
    case WEDNESDAY:
    numLetters = 9;
    break;
    };

    View Slide

  18. アロー形式
    • ラムダ式のようなアロー(->)が使える
    • わずらわしい`break`が不要
    switch (day) {
    case MONDAY, FRIDAY, SUNDAY:
    numLetters = 6;
    break;
    case TUESDAY:
    numLetters = 7;
    break;
    case THURSDAY, SATURDAY:
    numLetters = 8;
    break;
    case WEDNESDAY:
    numLetters = 9;
    break;
    };
    switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> numLetters = 6;
    case TUESDAY -> numLetters = 7;
    case THURSDAY, SATURDAY -> numLetters = 8;
    case WEDNESDAY -> numLetters = 9;
    };

    View Slide


  19. switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> numLetters = 6;
    case TUESDAY -> numLetters = 7;
    case THURSDAY, SATURDAY -> numLetters = 8;
    case WEDNESDAY -> numLetters = 9;
    };
    numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY -> 7;
    case THURSDAY, SATURDAY -> 8;
    case WEDNESDAY -> 9;
    };

    View Slide

  20. yield
    • switch式において、アロー形式でブロックを使うときや既存の
    形式では`yield`で値を返す
    • Java12でのpreview1ではbreakだったけど、ラベル付きbreak
    とまぎらわしいのもあって変更された
    case TUESDAY -> {
    yield 7;
    }

    View Slide

  21. 言語機能
    • Text Blocks(Preview2)
    • Switch expression(Standard)
    • Records(Preview)
    • Pattern matching for instanceof(Preview)

    View Slide

  22. Records(Preview)
    • データをやりとりするための型
    • イミュータブル(値が変更できない)
    • 名前付きタプル
    • Case class(Scala) やData class(Kotlin), @Value(Lombok)

    View Slide

  23. 定義
    public record Rec(String name, int count) {}
    public class Rec extends Record {
    private final String name;
    private final int count;
    Rec(String name, int count) {
    this.name = name;
    this.count = count;
    }
    String name() { return name; }
    String count() { return count; }
    // toString, equals, hashCode
    }

    View Slide

  24. Objectメソッドのバイトコード
    • Invoke Dynamicが使われている
    • 実行時に処理コードが生成される
    • コンパイル時ではない
    • もし将来のバージョンでより最適な実装に変わったとしても、
    古いバージョンでコンパイルされたコードも新しい実装で動く
    public final boolean equals(java.lang.Object);
    Code:
    0: aload_0
    1: aload_1
    2: invokedynamic #27, 0
    // InvokeDynamic #0:equals:(LRec;Ljava/lang/Object;)Z
    7: ireturn

    View Slide

  25. 次のバージョンでは
    • Sealed Classes(Java15でJEP360としてPreview)
    • 継承するクラスを限定できる(インタフェースでもよい)
    • Switch式でdefaultが不要になる
    public sealed class Shape
    permits Circle, Rectangle, Square {...}
    Shape rotate(Shape shape, double angle) {
    return switch (shape) {
    case Circle c -> c; // no action needed
    case Rectangle r -> r.rotate(angle);
    case Square s -> s.rotate(angle);
    }
    }

    View Slide

  26. 言語機能
    • Text Blocks(Preview2)
    • Switch expression(Standard)
    • Records(Preview)
    • Pattern matching for instanceof(Preview)

    View Slide

  27. Pattern Matching for instanceof(Preview)
    • Kotlinのスマートキャストのような機能
    Object o = "test";
    if (o instanceof String s) {
    System.out.println(s.length());
    }
    Object o = "test";
    if (o instanceof String) {
    String s = (String) o;
    System.out.println(s.length());
    }

    View Slide

  28. Byte code
    public static void main(java.lang.String...);
    Code:
    0: ldc #7 // String test
    2: astore_1
    3: aload_1
    4: astore_3
    5: aload_3
    6: instanceof #9 // class java/lang/String
    9: ifeq 35
    12: aload_3
    13: checkcast #9 // class java/lang/String
    16: dup
    17: astore_2
    18: aload_3
    19: checkcast #9 // class java/lang/String
    22: if_acmpne 35
    25: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
    28: aload_2
    29: invokevirtual #17 // Method java/lang/String.length:()I
    32: invokevirtual #21 // Method java/io/PrintStream.println:(I)V
    35: return
    Object o = "test";
    if (o instanceof String s) {
    System.out.println(s.length());
    }

    View Slide

  29. Byte code
    public static void main(java.lang.String...);
    Code:
    0: ldc #7 // String test
    2: astore_1
    3: aload_1
    4: astore_3
    5: aload_3
    6: instanceof #9 // class java/lang/String
    9: ifeq 35
    12: aload_3
    13: checkcast #9 // class java/lang/String
    16: dup
    17: astore_2
    18: aload_3
    19: checkcast #9 // class java/lang/String
    22: if_acmpne 35
    25: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
    28: aload_2
    29: invokevirtual #17 // Method java/lang/String.length:()I
    32: invokevirtual #21 // Method java/io/PrintStream.println:(I)V
    35: return
    Object o = "test";
    if (o instanceof String s) {
    System.out.println(s.length());
    }
    無駄では?

    View Slide

  30. Byte code - cast
    public static void main(java.lang.String...);
    Code:
    0: ldc #7 // String test
    2: astore_1
    3: aload_1
    4: instanceof #9 // class java/lang/String
    7: ifeq 25
    10: aload_1
    11: checkcast #9 // class java/lang/String
    14: astore_2
    15: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
    18: aload_2
    19: invokevirtual #17 // Method java/lang/String.length:()I
    22: invokevirtual #21 // Method java/io/PrintStream.println:(I)V
    25: return
    Object o = "test";
    if (o instanceof String) {
    String s = (String) o;
    System.out.println(s.length());
    }

    View Slide

  31. Byte code(Java 15 ea 22)
    public static void main(java.lang.String...);
    Code:
    0: ldc #7 // String test
    2: astore_1
    3: aload_1
    4: astore_3
    5: aload_3
    6: instanceof #9 // class java/lang/String
    9: ifeq 27
    12: aload_3
    13: checkcast #9 // class java/lang/String
    16: astore_2
    17: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
    20: aload_2
    21: invokevirtual #17 // Method java/lang/String.length:()I
    24: invokevirtual #21 // Method java/io/PrintStream.println:(I)V
    27: return
    ここでは無駄だけどもっと複雑な式の場合には必要。きっとJITで省かれる
    Object o = "test";
    if (o instanceof String s) {
    System.out.println(s.length());
    }

    View Slide

  32. これからのバージョンでは
    • Pattern with switch
    • switchでパターンマッチを使う
    • Deconstruction
    • レコードの分解
    switch (obj) {
    case String s -> parseInt(s);
    case Integer i -> i;
    default -> 0;
    }
    switch (obj) {
    case Add(int l, int r) -> l + r; // record Add(int l, int r)
    case Sub(int l, int r) -> l - r; // record Sub(int l, int r)
    case Num(int i) -> i; // record Num(int i)
    default -> throw new UnsupportedOparation();
    }

    View Slide

  33. ライブラリ
    • Helpful NullPointerException
    • JFR event streaming
    • Foreign Memory Access(Incubator)

    View Slide

  34. ライブラリ
    • Helpful NullPointerException
    • JFR event streaming
    • Foreign Memory Access(Incubator)

    View Slide

  35. Helpful NullPointerException
    • JavaプログラマはNPEが大好きだけどメッセージが不親切
    • Java 14ではNPEのメッセージが親切になる
    String s = null;
    println(s.length());
    Exception in thread "main" java.lang.NullPointerException
    at Sample.main(mysample.java:4)
    String s = null;
    println(s.length());
    Exception in thread "main" java.lang.NullPointerException:
    Cannot invoke "String.length()" because "Sample.s" is null
    at Sample.main(mysample.java:4)

    View Slide

  36. これでもっとNPEが大好きに!

    View Slide

  37. Helpful NullPointerException
    • `-XX:+ShowCodeDetailsInExceptionMessages`が必要
    • 将来のバージョンではデフォルトに
    • JShellの場合
    • `-R-XX:+ShowCodeDetailsInExceptionMessages`をつける

    View Slide

  38. ライブラリ
    • Helpful NullPointerException
    • JFR event streaming
    • Foreign Memory Access(Incubator)

    View Slide

  39. JFRとは?
    • JFR(JDK Flight Recorder) はOpenJDK 11でオープンソースと
    して導入
    • それまではOracle JDKの商用機能だった
    • 名前もJava Flight Recorder
    • 飛行機のフライトレコーダのようにJVMの実行時の状況を確認
    する
    • データはファイルにダンプされる
    • 同じくオープンソース化されたJMCで
    データを見る
    • (JDK Mission Control)

    View Slide

  40. JFR Event Streaming
    • イベントとして処理できるようになったので監視に使いやすく
    なった

    View Slide

  41. ライブラリ
    • Helpful NullPointerException
    • JFR event streaming
    • Foreign Memory Access(Incubator)

    View Slide

  42. Foreign Memory Access API
    • Javaヒープ外のメモリを扱う
    • 大きいメモリ
    • GCの影響を排除する
    • これまでのオフヒープメモリの利用方法
    • Unsafe
    • 安全ではない
    • 解放済みメモリにアクセスするとJVMがクラッシュする
    • nioのDirect ByteBuffer
    • intでインデックスアクセスするので2GBまで
    • メモリの解放はGC依存
    • JNI
    • めんどい
    • Cヘッダーが必要
    • 遅い

    View Slide

  43. @PreviewFeature
    • Java 13まで
    • preview機能用のAPIは単に@Deprecated
    • ‘—enable-feature’なしで使えていた
    • Java 14から
    • @PreviewFeatureアノテーションが導入された
    • preview機能関連のAPIを使うには‘—enable-feature’が必要
    • String#formatted

    View Slide

  44. ツール
    • Packaging Tool(Incubator)

    View Slide

  45. Packaging Tool
    • Javaランタイムを含んだアプリケーションパッケージ
    • ネイティブのパッケージングフォーマット
    • Windows
    • exe, msi
    • macOS
    • pkg, dmg
    • Linux
    • deb, rpm

    View Slide

  46. 手順
    • コンパイル
    • javac App.class
    • JARの作成
    • jar cf target/app.jar App.class
    • パッケージの作成
    • jpackage --name myapp --input target --main-jar app.jar --main-
    class App

    View Slide

  47. 結果
    • 45MBのインストーラ
    • 124MBのアプリサイズ
    • アンインストーラも作成される
    • メニューの登録
    • --win-menu

    View Slide

  48. もっとコンパクトにしたい場合
    • カスタムランタイム
    • 最低限のモジュールを含んだJavaランタイム
    • カスタムランタイムの作成
    • jlink --add-modules `jdeps --print-module-deps App.class` --output
    myrt
    • カスタムランタイムを使ったパッケージの作成
    • jpackage --name myapp_min --input target --main-jar app.jar --
    main-class App --runtime-image myrt
    • 結果
    • 28MBのインストーラ、78MBのアプリ

    View Slide

  49. もっと詳しく
    • 「Java 14」でぐぐる

    View Slide