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. Java 14がリリースされてますね • 3/17にリリース • 16 JEPs • 主な新機能はJEPとして まとめられている

    • non LTS • パッチはJava15が出るまで • 現在は14.0.1がリリース • 7月の14.0.2まで • 次のLTSは17(2021年9月)
  2. 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
  3. 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
  4. ところで試用機能について • 試用機能 • 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ではない)
  5. Text Blocks(Preview 2) • 複数行のテキスト • ダブルクオート3つで囲む • Raw Stringsとして12で導入されかけたけどバッククオートが

    もったいないとして取り下げ • Text BlocksとしてJava 13でPreviewとして入った。15で Standardになる予定(JEP 378) """ <head> <title>Java 14</title> </head> """
  6. var s = """ <head> <title>Java 14</title> </head> """; var

    s = """ <head> <title>Java 14</title> </head> """; var s = """ <head> <title>Java 14</title> </head> """; インデント • 一番ひだりにあわせられる `<head>`の位置が基準 閉じ側の`"""`の位置が基準 `<head>`の位置が基準
  7. エスケープ • 14でのPreview2で入った • 改行のエスケープ(¥) • スペース文字(¥s) • 行末のスペースは無視される •

    行末にスペースが欲しいときは ‘¥s’を入れる var s = """ Lorem ipsum dolor ¥ sit amet consectetur ¥s """; var s = "Lorem ipsum dolor sit amet consectetur ";
  8. 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; }
  9. 複数の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; };
  10. アロー形式 • ラムダ式のようなアロー(->)が使える • わずらわしい`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; };
  11. 式 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; };
  12. 定義 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 }
  13. 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
  14. 次のバージョンでは • 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); } }
  15. 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()); }
  16. 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()); }
  17. 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()); } 無駄では?
  18. 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()); }
  19. 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()); }
  20. これからのバージョンでは • 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(); }
  21. 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)
  22. JFRとは? • JFR(JDK Flight Recorder) はOpenJDK 11でオープンソースと して導入 • それまではOracle

    JDKの商用機能だった • 名前もJava Flight Recorder • 飛行機のフライトレコーダのようにJVMの実行時の状況を確認 する • データはファイルにダンプされる • 同じくオープンソース化されたJMCで データを見る • (JDK Mission Control)
  23. Foreign Memory Access API • Javaヒープ外のメモリを扱う • 大きいメモリ • GCの影響を排除する

    • これまでのオフヒープメモリの利用方法 • Unsafe • 安全ではない • 解放済みメモリにアクセスするとJVMがクラッシュする • nioのDirect ByteBuffer • intでインデックスアクセスするので2GBまで • メモリの解放はGC依存 • JNI • めんどい • Cヘッダーが必要 • 遅い
  24. @PreviewFeature • Java 13まで • preview機能用のAPIは単に@Deprecated • ‘—enable-feature’なしで使えていた • Java

    14から • @PreviewFeatureアノテーションが導入された • preview機能関連のAPIを使うには‘—enable-feature’が必要 • String#formatted
  25. 手順 • コンパイル • javac App.class • JARの作成 • jar

    cf target/app.jar App.class • パッケージの作成 • jpackage --name myapp --input target --main-jar app.jar --main- class App
  26. もっとコンパクトにしたい場合 • カスタムランタイム • 最低限のモジュールを含んだ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のアプリ