Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

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

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

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

Naoki Kishida

March 16, 2021
Tweet

More Decks by Naoki Kishida

Other Decks in Programming

Transcript

  1. 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が出ればバグ修正など は行われなくなる。
  2. Java 16 • 2021/3/16リリース • non-LTS • 次は17(Sept.2021) • 17個のJEP

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

    • 更新4個 • うち3個が正式化 http://openjdk.java.net/projects/jdk/16/ 正式化 正式化 更新 更新 正式化
  4. 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は残さない意向に見える
  5. 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
  6. 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
  7. ダウンロードサイト • 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
  8. 言語仕様 • Pattern Matching for instanceof(Standard) • Records(Standard) • Sealed

    Classes(Second Preview) • Warnings for Value-Based Classes
  9. 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()); }
  10. 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で宣言
  11. 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 } 要素(コンポーネント)を定義
  12. 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 } 中かっこが必要 追加のメソッドなどの定義も可
  13. 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
  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 } java.lang.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 } コンポーネントに 対応するフィールド private final
  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 } コンポーネントと同名の アクセスメソッド getterではない
  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 } オブジェクトの基本メソッドも 実装される
  19. カノニカル(正規)コンストラクタ • コンポーネントと同じパラメータとフィールド初期化が必要 record Rec(String name, int count) { Rec(String

    name, int count) { this.name = name; this.count = Math.max(count, 0); } } コンポーネントと同じ パラメータが必要
  20. Preview機能 • 言語機能の試用版 • 基本的にpreview, second previewの2回のpreviewを経て正式 化する • 正式化までに3バージョン必要

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

    | シール・クラスはプレビュー機能であり、デフォルトで無効になっています。 | (シール・クラスを有効にするには--enable-previewを使用します) | sealed class Hoge{} | ^
  22. 現状では使い道なし • 本当は次のように書けるといい • 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 "正方形"; } }
  23. 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 {}
  24. API • Vector API(Incubator) • Foreign Memory Access API(3rd Incubator)

    • Foreign Linker API(Incubator) • Unix-Domain Socket Channels
  25. 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); } }
  26. どんなハードウェアで使える? • IntelハイエンドだとAVX512に対応 • double(64bit) x 8 • なんだけど、i7 7820Xでdouble

    x 4までしか使えず • ほかのi7やi5などは256bit • M1は128bit • double x 2 • float x 4
  27. • 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); }
  28. 結果 • Vector版 9.7秒 • 通常版 6.3秒 • おそい・・・ •

    JITがきいてない • 複雑な処理ではまだパフォーマンスが出なさそう
  29. 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); } }
  30. 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
  31. Alpine Linux • musl • c標準ライブラリ • glibc互換 • コンパクトに整理されている

    • ヘッダが人間にも読める • glibcは#ifdefたくさんで読みにくい • busybox • すべてのコマンドがbusyboxにsymbolic link • apk • パッケージ管理
  32. パッチ • ダミー変数に割り当てる 672c672 < alloca(((pid ^ counter++) & 7)

    * 128); --- > int* dummy = (int*)alloca(((pid ^ counter++) & 7) * 128);
  33. 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
  34. --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
  35. もっと削ってみる • 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