JEPで語る方もおなじみになってきました。
Java 27のJEPは全部で9つ。そのうち、Standard JEPは4つで、Preview JEPとIncubator JEPは5つです。
Java 27のStandard JEPの一覧はこちら。
- JEP 523: Make G1 the Default Garbage Collector in All Environments
- JEP 527: Post-Quantum Hybrid Key Exchange for TLS 1.3
- JEP 534: Compact Object Headers by Default
- JEP 536: JFR In-Process Data Redaction
Standard JEPのうちAPIの変更されるのはJEP 527ですが、既存のコードのままでも恩恵を受けることができます。
Preview JEPとIncubator JEPの一覧はこちら。
- JEP 531: Lazy Constants (Third Preview)
- JEP 532: Primitive Types in Patterns, instanceof, and switch (Fifth Preview)
- JEP 533: Structured Concurrency (Seventh Preview)
- JEP 537: Vector API (Twelfth Incubator)
- JEP 538: PEM Encodings of Cryptographic Objects (Third Preview)
いつもと同じように、PreviewやIncubatorは軽く触れるだけで、主にStandard JEPについて紹介していきます。
ただし、JEP 527とJEP 538はセキュリティ関連なので省略します。
JEP 523: Make G1 the Default Garbage Collector in All Environments
サーバー環境でG1GCがデフォルトのGCになったのがJava 9。
STWを減らすために、アプリケーションスレッドと同時にGCスレッドも動作するので、本来はコアがたくさんあるような環境が適しているのは明らかです。また、ヒープをリージョンに分割するのも、ヒープがある程度余裕がないとリージョンを効果的に使えません。
したがって、リソースに余裕があるサーバー環境でG1GCがデフォルトGCというのは理にかなっています。
しかし、G1GCは着実に改良され続けて、低リソース環境でもシリアルGCと同等のスループットを得ることができるようになってきました。これってなにげにすごいことだと思うんですよね。
ということで、今まで低リソース環境ではシリアルGCがデフォルトGCだったのを、Java 27からG1GCがデフォルトGCになりました。
とはいうものの、本当にシリアルGCと同じスループットが出るかどうかはアプリケーションごとに検証が必要かもしれません。
低リソース環境といえばコンテナで動かしている場合ですね。今までシリアルGCを使用していたのであれば、G1GCを評価しておいた方がよいかもしれません。
ただ、Java 27はLTSではないので、実際に使われるのはLTSのJava 29でしょう。Java 29がリリースされるまで時間的に余裕があるので、急いで評価する必要はないかもしれないですね。
JEP 534: Compact Object Headers by Default
JEP 534もJEP 523と同様にデフォルト動作の変更です。
何が変更になったのかというと、オブジェクトヘッダーです。
Project Lilliputで進めていたオブジェクトヘッダーのコンパクト化はJava 25で導入されました(JEP 519)。しかし、この時はコンパクトオブジェクトヘッダーを試すには、Javaのオプションで -XX:+UseCompactObjectHeaders を指定する必要がありました。
そして、コンパクトオブジェクトヘッダーが導入されて1年、とうとうコンパクトオブジェクトヘッダーがデフォルトになったのでした。
逆に以前のオブジェクトヘッダーを使用するには、Javaのオプションで -XX:-UseCompactObjectHeaders を指定します。
JEP 536: JFR In-Process Data Redaction
Redactionは編集という意味なのですが、閲覧できないように黒塗りにすることもRedactionなのだそうです。
何を黒塗りするかというと、Javaの起動時オプションで指定した機密情報です。
JDK Flight Recorder (JFR)はアプリケーションの診断やプロファイリングに使う情報を収集する便利なフレームワークです。
JFRではいろいろな情報を収集するのですが、その中には起動時オプションも含まれます。
しかし、起動時オプションには公になっていないURIや、パスワードなどを指定することもあります。このため、JFRの記録ファイルから情報漏洩の可能性が発生してしまいます。
自分では解析できないので、第三者に記録ファイルを渡して解析してもらうようなケースですね。
そこで、機密情報に当たるような起動時オプションは記録しないようにしましょうというのが、JEP 536です。
これ、自分で黒塗りにするところを指定するのだと思っていたら、デフォルトのままでも結構黒塗りにしてくれます。たとえば、次のようにTestクラスを実行したとします。
> java -XX:StartFlightRecording:filename=dump.jfr Test -password abcde
Testクラスの引数として-passwordでパスワードを指定するようなパターンです。
Testクラスの実行後、JDK Mission Control (JMC)でdump.jfrファイルを読み込んでみましょう。下図はJMCのシステムプロパティの一覧です。
sun.java.commandのところを見てみると"Test [REDACTED] [REDACTED]"になっています。つまり、この引数がパスワードであると判別して記録しないようになっているわけです。
しかし、passwordではなく、psswrdやpassだとRedactしないようです。
そこで、デフォルトでRedactしない情報については、個別に指定する必要が出てきます。
Redactする情報は -XX:FlightRecorderOptions オプションで指定します。
-XX:FlightRecorderOptions オプションの後に、以下の2種類のサブオプションで情報を指定します。
- redact-aargument: コマンドライン引数
- redact-key: 環境変数もしくはシステムプロパティ
たとえば、デフォルトではRedactされなかった-psswrdとその後の情報をRedactするには以下のように指定します。
> java -XX:StartFlightRecording:filename=dump.jfr -XX:FlightRecorderOptions:'reduct-argument=-psswrd *' Test -psswrd abcde
*は任意の文字列にマッチするワイルドカードです。1文字にマッチする?も使用できます。
このように指定することで、JFRの記録ファイルからの機密情報漏洩を防ぐことができます。
Preview JEP/Incubator JEP
お試し機能のJEPも簡単に了解しましょう。
JEP 531: Lazy Constants (Third Preview)
JEP 531は3回目のプレビューですが、Lazy Constantsになってからは2回目。
Lazy Constantsは、初期化に時間のかかるオブジェクトを遅延初期化させるためのAPIです。
Java 27での変更は少しだけ。
isInitializedメソッドとorElseメソッドの削除と、Set.ofLazyメソッドの追加です。
もともとそれほど大きくないAPIですし、変更も少しなので、そろそろStandard JEPになりそうな感じ。
Java 28で変更なしでもう一度Preview、Java 29でStandard JEPというのが櫻庭の予想ですw
JEP 532: Primitive Types in Patterns, instanceof, and switch (Fifth Preview)
パターンマッチングにプリミティブ型を使えるようにしようというのがJEP 532。
Java 27では変更なしでもう一度Previewなので、Java 28でStandard JEPになるのでしょう。
JEP 532についてはカサレアルのブログに詳しく書いたので、そちらをご参照ください!
switchのパターンマッチングにプリミティブ型を使う
https://bsblog.casareal.co.jp/archives/14973
JEP 533: Structured Concurrency (Seventh Preview)
複数のスレッドで実行した結果をまとめるような用途に使用するのがStructured Concurrencyです。
Structured ConcurrencyはProject Loomで仕様策定されているので、もともとはVirtual Threadと一緒に出せればよかったのですが、なんと今回7回目のプレビュー。
しかし、Java 28でStandard JEPになることがほぼ決まりました!
とはいうものの、Java 27でも変更点があります。
- StructuredTaskScopeインタフェースとStructuredTaskInterface.Joinerインタフェースにjoin()メソッドなどでスローさrふぇる例外の型を表す型パラメータが追加
- StructuredTaskScopeインタフェースに、引数にStructuredTaskScope.Configurationインタフェースをとるopen()メソッドのオーバーロードが追加
- allSuccessfulOrThrow()メソッドなどのファクトリーメソッドで生成されるStructuredTaskInterface.Joinerオブジェクトが、joinメソッドでExecutionException例外をスローするように変更
- StructuredTaskScopeインタフェースのawaitAll()メソッドが削除
- StructuredTaskScope.JoinerインタフェースのonTimeout()メソッドがtimeout()メソッドに名称変更
JEP 537: Vector API (Twelfth Incubator)
Value Classが正式にサポートされるまでIncubatorが続くVector APIです。
Java 27でも変更なしでIncubatorが続きます。
このまま永遠にIncubatorのままなのではないかと思われたのですが、ここに来て動きが!というのも、Java 28でValue ClassがPreview JEP (JEP 401)になります!
すぐにStandard JEPになることは考えられないですけど、次の次のLTSには間に合うかなぁ....???
そうしたら、やっとVector APIもStandard JEPへ!
まとめ
Java 27では、JEPで語れない方のAPI変更は少なかったですが、JEPの変更も少な目。
目新しいものはありませんし、Standard JEPになったのもデフォルト動作の変更なので。
まぁ、毎回派手に新機能が入るわけではないので、しかたありません。
しかし、次のJava 28では、いろいろと変化がありそうです。Value Classだけでなく、新しいJSON APIやLeydenの新しいJEPも含まれています。
楽しみに待つことにしましょう!









