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

Java16新機能-言語とAPIを中心に- / Java 16 new features - about lang and API -

Java16新機能-言語とAPIを中心に- / Java 16 new features - about lang and API -

2021/3/16に開催されたJJUG night seminarでの登壇資料です
https://jjug.doorkeeper.jp/events/119184

9e840766611f942c7c0a9ad6987a5d78?s=128

Naoki Kishida

March 16, 2021
Tweet

Transcript

  1. Java 16新機能 言語とAPIを中心に あとAlpine Linux JJUG Night Seminar 2021/3/16 LINE

    Fukuoka きしだ なおき
  2. Java 16 • 2021/3/16リリース • non-LTS • 次は17(Sept.2021) • 17個のJEP

    http://openjdk.java.net/projects/jdk/16/
  3. Java 16 • 2021/3/16リリース • non-LTS • 次は17(Sept.2021) • 17個のJEP

    http://openjdk.java.net/projects/jdk/16/ LTS(Long Term Support) 長期サポート 6バージョンごとにLTSが設定されて長期間の サポートが行われる。 現在のLTSは11で、次回は17。 15はLTSではないので16が出ればバグ修正など は行われなくなる。
  4. Java 16 • 2021/3/16リリース • non-LTS • 次は17(Sept.2021) • 17個のJEP

    http://openjdk.java.net/projects/jdk/16/
  5. Java 16 • 2021/3/16リリース • non-LTS • 次は17(Sept.2021) • 17個のJEP

    http://openjdk.java.net/projects/jdk/16/ JEP(JDK Enhancement Proposal) 機能改善のまとめ 主な仕様変更はJEPとしてまとめられている
  6. Java 16 • 2021/3/16リリース • non-LTS • 次は17(Sept.2021) • 17個のJEP

    • 更新4個 • うち3個が正式化 http://openjdk.java.net/projects/jdk/16/ 正式化 正式化 更新 更新 正式化
  7. Java 16 • 2021/3/16リリース • non-LTS • 次は17(Sept.2021) • 17個のJEP

    • 更新4個 • うち3個が正式化 http://openjdk.java.net/projects/jdk/16/ 正式化 正式化 更新 更新 正式化 Javaの試用機能 大きな新機能について試用版として導入することで フィードバックを得やすくしてよりよい機能を提供 できるようにする • 言語機能:Preview • API:Incubator • JVM機能:Experimental 17LTSにはPreviewは残さない意向に見える
  8. JEP • 言語仕様 • Pattern Matching for instanceof • Records

    • Sealed Classes(Second Preview) • Warnings for Value-Based Classes • API • Foreign Memory Access API (Third Incubator) • Vector API(Incubator) • Foreign Linker API(Incubator) • Unix-Domain Socket Channels • Tool • Packaging Tool • JVM • ZGC: Concurrent Thread-Stack Processing • Elastic Metaspace • Strongly Encapsulate JDK Internals by Default • OpenJDK • Migrate from Mercurial to Git • Migrate to GitHub • Enable C++14 Language Features • Alpine Linux Port • Windows/AArch64 Port
  9. JEP • 言語仕様 • Pattern Matching for instanceof • Records

    • Sealed Classes(Second Preview) • Warnings for Value-Based Classes • API • Foreign Memory Access API (Third Incubator) • Vector API(Incubator) • Foreign Linker API(Incubator) • Unix-Domain Socket Channels • Tool • Packaging Tool • JVM • ZGC: Concurrent Thread-Stack Processing • Elastic Metaspace • Strongly Encapsulate JDK Internals by Default • OpenJDK • Migrate from Mercurial to Git • Migrate to GitHub • Enable C++14 Language Features • Alpine Linux Port • Windows/AArch64 Port
  10. ダウンロードサイト • Oracle OpenJDK • http://jdk.java.net/16/ • AdoptOpenJDK • https://adoptopenjdk.net/?variant=openjdk16&jvmVariant=hotspot

    • Amazon Corretto • https://github.com/corretto/corretto-jdk/releases/tag/16.0.0.36.1 • Azul Zulu Community • https://jp.azul.com/downloads/zulu-community/?version=java-16- ea&architecture=x86-64-bit&package=jdk • Liberica JDK • https://bell-sw.com/pages/java-16/ • Oracle JDK • https://www.oracle.com/java/technologies/javase-jdk16-downloads.html
  11. 言語仕様 • Pattern Matching for instanceof(Standard) • Records(Standard) • Sealed

    Classes(Second Preview) • Warnings for Value-Based Classes
  12. Pattern Matching for instanceof(Standard) • 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()); }
  13. Records(Standard) • データをやりとりするための型 • イミュータブル(値が変更できない) • 名前付きタプル • Case class(Scala)

    やData class(Kotlin), @Value(Lombok)
  14. Recordの定義 public record Rec(String name, int count) {} public final

    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 } recordで宣言
  15. Recordの定義 public record Rec(String name, int count) {} public final

    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 } 要素(コンポーネント)を定義
  16. Recordの定義 public record Rec(String name, int count) {} public final

    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 } 中かっこが必要 追加のメソッドなどの定義も可
  17. Recordの定義 public record Rec(String name, int count) {} public final

    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 } 暗黙にfinal
  18. Recordの定義 public record Rec(String name, int count) {} public final

    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 } java.lang.Recordを継承
  19. Recordの定義 public record Rec(String name, int count) {} public final

    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 } コンポーネントに 対応するフィールド private final
  20. Recordの定義 public record Rec(String name, int count) {} public final

    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 } コンストラクタが定義される
  21. Recordの定義 public record Rec(String name, int count) {} public final

    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 } コンポーネントと同名の アクセスメソッド getterではない
  22. Recordの定義 public record Rec(String name, int count) {} public final

    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 } オブジェクトの基本メソッドも 実装される
  23. Recordの利用 • 利用時は普通のクラスと同様 Rec r = new Rec("Java", 15);

  24. カノニカルコンストラクタ • コンストラクタの定義では、引数にコンポーネントをその型で その順番で、そしてそれだけを書く必要がある • コンポーネントに対応する内部フィールドを必ず初期化しない といけない • カノニカル(正規)コンストラクタ

  25. カノニカル(正規)コンストラクタ • コンポーネントと同じパラメータとフィールド初期化が必要 record Rec(String name, int count) { Rec(String

    name, int count) { this.name = name; this.count = Math.max(count, 0); } } コンポーネントと同じ パラメータが必要
  26. カノニカル(正規)コンストラクタ • コンポーネントと同じパラメータとフィールド初期化が必要 record Rec(String name, int count) { Rec(String

    name, int count) { this.name = name; this.count = Math.max(count, 0); } } フィールド初期化が必須
  27. コンパクトコンストラクタ • 必ず書かないといけないものは省略していいのでは? record Rec(String name, int count) { Rec

    { count = Math.max(count, 0); } } パラメータを省略
  28. コンパクトコンストラクタ • 必ず書かないといけないものは省略していいのでは? record Rec(String name, int count) { Rec

    { count = Math.max(count, 0); } } フィールドを初期化してはいけない
  29. Sealed Classes(2nd Preview) • 継承できるクラスを限定する • shield(盾) classではなくてsealed(密閉された) class public

    abstract sealed class Shape permits Circle, Rectangle, Square {...}
  30. Preview機能 • 言語機能の試用版 • 基本的にpreview, second previewの2回のpreviewを経て正式 化する • 正式化までに3バージョン必要

    • 明確な決まりがあるわけではない • javacやjavaコマンドなどで`--enable-preview`が必要 • `-source`でのバージョン指定も必要 jshell> sealed class Hoge{} | エラー: | シール・クラスはプレビュー機能であり、デフォルトで無効になっています。 | (シール・クラスを有効にするには--enable-previewを使用します) | sealed class Hoge{} | ^
  31. ( ´∀`)<シールドクラス • 公式にはシール・クラス? jshell> sealed class Hoge{} | エラー:

    | シール・クラスはプレビュー機能であり、デフォルトで無効になっています。 | (シール・クラスを有効にするには--enable-previewを使用します) | sealed class Hoge{} | ^
  32. 現状では使い道なし • 本当は次のように書けるといい • Pattern matching for switchなどが来れば便利に(Java 18かな) String

    getName(Shape s) { if (s instanceof Circle) { return "円"; } else if (s instanceof Rectangle) { return "四角"; } else if (s instanceof Square) { return "正方形"; } }
  33. Sealed Classesの階層 • Sealed Classを継承する場合、sealed・final・non-sealedの いずれかが必要 • recordは暗黙的にfinal Hoge Foo

    Bar Baz sealed 要 sealed 要 final or non-sealed 要 final or non-sealed MyBaz Bazがnon-sealedであれば 継承できる。sealされない sealed class Hoge permits Foo, Bar {} final class Foo extends Hoge {} sealed class Bar extends Hoge permits Baz {} non-sealed class Baz extends Bar {} class MyBaz extends Baz {}
  34. non-sealed • ハイフン入りキーワード! • 実際はキーワードではない • switch式のときにbreak-withが検討されていた • package-privateなども可能

  35. API • Vector API(Incubator) • Foreign Memory Access API(3rd Incubator)

    • Foreign Linker API(Incubator) • Unix-Domain Socket Channels
  36. Vector API(Incubator) • AVX命令のような、複数のデータに対する計算を同時に行う 命令(SIMD - Single Instruction Multiple Data)をJavaから利用

    import jdk.incubator.vector.*; static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256; void vectorComputation(float[] a, float[] b, float[] c) { // SPECIES.length() = 256bit / 32bit -> 8 for (int i = 0; i < a.length; i += SPECIES.length()) { // 端数がマスクされる // a.lengthが11でiが8のとき最初の3つしか要素がないので [TTT.....] VectorMask<Float> m = SPECIES.indexInRange(i, a.length); FloatVector va = FloatVector.fromArray(SPECIES, a, i, m); FloatVector vb = FloatVector.fromArray(SPECIES, b, i, m); FloatVector vc = va.mul(va). add(vb.mul(vb)). neg(); vc.intoArray(c, i, m); } }
  37. どんなハードウェアで使える? • IntelハイエンドだとAVX512に対応 • double(64bit) x 8 • なんだけど、i7 7820Xでdouble

    x 4までしか使えず • ほかのi7やi5などは256bit • M1は128bit • double x 2 • float x 4
  38. • SmallPT レイトレやってみる https://github.com/kishida/smallpt4j/blob/vector/src/main/java/naoki/smallpt/SmallPT.java public class SmallPT { private static

    final int SAMPLES_DEFAULT = 40; private static final VectorSpecies<Double> SPECIES = DoubleVector.SPECIES_256; static DoubleVector fromValues(double x, double y, double z) { return DoubleVector.fromArray(SPECIES, new double[]{x, y, z, 0}, 0); } static DoubleVector normalize(DoubleVector v) { double dist = sqrt(v.mul(v).reduceLanes(VectorOperators.ADD)); return v.div(dist); } static double dot(DoubleVector v, DoubleVector b) { return v.mul(b).reduceLanes(VectorOperators.ADD); } // cross: static VectorShuffle yzx = VectorShuffle.fromValues(SPECIES, 1, 2, 0, 3); static DoubleVector mod(DoubleVector v, DoubleVector b) { // return v.rearrange(yzx).mul(b.rearrange(zxy)).sub(v.rearrange(zxy).mul(b.rearrange(yzx))); return v.mul(b.rearrange(yzx)).sub(v.rearrange(yzx).mul(b)).rearrange(yzx); }
  39. 結果 • Vector版 9.7秒 • 通常版 6.3秒 • おそい・・・ •

    JITがきいてない • 複雑な処理ではまだパフォーマンスが出なさそう
  40. Foreign memory Access API(3rd incubator) • 大量データを処理するために、GCで管理されないメモリを 確保する • 標準ではないUnsafeを使っていたものを標準APIで実現する

    • --add-modules jdk.incubator.foreign が必要 import jdk.incubator.foreign.*; try (MemorySegment segment = MemorySegment.allo cateNative(100)) { for (int i = 0 ; i < 25 ; i++) { MemoryAccess.setIntAtOffset(i * 4, i); } }
  41. One more thing!

  42. Stream.toList()

  43. Stream.toList() • collector(Collectors.toUnmodifiableList())と書く必要 がなくなった! • 変更不可のリストなのでCollectors.toList()を置き換える ときは注意 C:¥Users¥naoki>java¥jdk¥jdk-16¥bin¥jshell | JShellへようこそ

    -- バージョン16 | 概要については、次を入力してください: /help intro jshell> Stream.of("a","b","c").toList() $1 ==> [a, b, c] jshell> /var $1 | List<String> $1 = [a, b, c] jshell> $1.getClass() $2 ==> class java.util.ImmutableCollections$ListN
  44. OpenJDK • Windows/AArch64 Port • Alpine Linux Port

  45. ARM Mac対応は17っぽい • まだ一覧には のってない

  46. Alpine Linuxで最小Docker Imageを作る

  47. Alpine Linux • musl • c標準ライブラリ • glibc互換 • コンパクトに整理されている

    • ヘッダが人間にも読める • glibcは#ifdefたくさんで読みにくい • busybox • すべてのコマンドがbusyboxにsymbolic link • apk • パッケージ管理
  48. 16にはまだAlpineバイナリがない・・・ • JDK 16 RC http://jdk.java.net/16/

  49. では自分でビルドだ • bash configure make • ソースはGitHub https://github.com/openjdk/jdk/tree/jdk-16+36

  50. ビルドエラー (T^T) • allocaの戻り値を使っていないという警告が

  51. パッチ • ダミー変数に割り当てる 672c672 < alloca(((pid ^ counter++) & 7)

    * 128); --- > int* dummy = (int*)alloca(((pid ^ counter++) & 7) * 128);
  52. 結構大きい • Spring Boot+Spring MVCのHello Worldを動かす • 961MB

  53. jlinkで実行環境を最適化 • 必要なモジュールだけを持つJava実行環境をつくる • jdepsで必要なモジュールを確認する • Springのようなfat-jarでは一度展開してライブラリjarを取り出して おく必要がある > jlink

    --compress 2 --strip-debug --no-header-files --no-man-pages --output /src/jre --add-modules java.base,java.desktop,java.instrument,java.management.rmi,java.naming,java.pref s,java.scripting,java.security.jgss,java.sql,jdk.httpserver,jdk.jfr,jdk.unsuppor ted
  54. 77MB • 77MBのイメージができた

  55. 参考 • UbuntuやJibを使ってみる

  56. Shenandoahとかいらなくない? • 使わない機能がたくさんある • Javaには6つのGCがある • 1つしか使わない • 削ってみる

  57. --disable-jvm-feature • 使わないものを無効にしてみる bash configure --disable-jvm-feature-aot --disable-jvm-feature-graal --disable- jvm-feature-parallelgc --disable-jvm-feature-shenandoahgc

    --disable-jvm-feature- zgc --disable-jvm-feature-epsilongc --disable-jvm-feature-jvmci --disable-jvm- feature-jni-check --disable-jvm-feature-dtrace
  58. 結果:そんな小さくない • 74MB

  59. もっと削ってみる • JITいらんくない? • Serial GCでよくない? • 管理しねーし bash configure

    --disable-jvm-feature-aot --disable-jvm-feature-graal -- disable-jvm-feature-parallelgc --disable-jvm-feature-shenandoahgc -- disable-jvm-feature-zgc --disable-jvm-feature-epsilongc --disable-jvm- feature-jvmci --disable-jvm-feature-jni-check --disable-jvm-feature-dtrace --disable-jvm-feature-cds --disable-jvm-feature-compiler1 --disable-jvm- feature-compiler2 --disable-jvm-feature-jvmti --disable-jvm-feature-jfr -- disable-jvm-feature-management --disable-jvm-feature-g1gc --disable-jvm- feature-services --disable-jvm-feature-nmt --disable-jvm-feature-vm-structs --disable-jvm-feature-link-time-opt
  60. 60MB! • だいぶ小さくなった

  61. 結果 • すごく小さいです! 0 50 100 150 200 250 Alpine最小

    Alpineほどほど Alpine Ubuntu Jib
  62. うごいた! • 動きます • でも遅い • 2秒→9秒

  63. まとめ • recordとtoList便利そう