Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

chiroitoによる再現

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

ところで試用機能について • 試用機能 • 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ではない)

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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; }

Slide 17

Slide 17 text

複数の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; };

Slide 18

Slide 18 text

アロー形式 • ラムダ式のようなアロー(->)が使える • わずらわしい`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; };

Slide 19

Slide 19 text

式 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; };

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

定義 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 }

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

次のバージョンでは • 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); } }

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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()); }

Slide 28

Slide 28 text

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()); }

Slide 29

Slide 29 text

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()); } 無駄では?

Slide 30

Slide 30 text

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()); }

Slide 31

Slide 31 text

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()); }

Slide 32

Slide 32 text

これからのバージョンでは • 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(); }

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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)

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

ツール • Packaging Tool(Incubator)

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

もっとコンパクトにしたい場合 • カスタムランタイム • 最低限のモジュールを含んだ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のアプリ

Slide 49

Slide 49 text

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