JDK21 の変更点まとめ(JEP外)

blog1.mammb.com

JEP 外の JDK 21 における変更点を、開発時に覚えておきたいものに絞りまとめておきます。


Math.clamp() メソッドの追加

最小値と最大値で切り詰める場合は以下のようにしていました。

Math.min(max, Math.max(value, min));

以下が可能になりました。

Math.clamp(value, min, max);

int long float double のオーバーロードがあります。

StrictMath.clamp() にも同様のメソッドが追加されていますが、これは単に Math.clamp()に委譲しているだけです。


範囲指定可能な String.indexOf()

String クラスに以下のメソッドが追加されました。

public int indexOf(int ch, int beginIndex, int endIndex) { ... }
public int indexOf(String str, int beginIndex, int endIndex) { ... }

旧来は、fromIndex が指定できる indexOf() のみであり、検索範囲の終端を指定することができませんできた。

endIndex を指定することで長い文字列の部分検索が効率化できます。endIndex は慣例に則り、excluded となっており、endIndex の要素は含まれません。


区切り文字を含めて分割する String.splitWithDelimiters()

split() は結果に区切り文字を含みません。

var string = "aa:bb::cc";
string.split(":"); // -> [aa, bb, , cc]

区切り文字を含めるには、ゼロ幅マッチの正規表現で以下のように頑張る必要があります。

string.split("(?<=:)");          // -> [aa:, bb:, :, cc]
string.split("(?=:)");           // -> [aa, :bb, :, :cc]
string.split("((?<=:)|(?=:))");  // -> [aa, :, bb, :, :, cc]

String クラスに splitWithDelimiters() が追加され、上記3つ目のケースがカバーされます。

public String[] splitWithDelimiters(String regex, int limit) { ... }

以下のようになります。

string.splitWithDelimiters(":", -1);  // -> [aa, :, bb, :, , :, cc]

Pattern にも同様のメソッドが追加されています。

Pattern.compile(regex).splitWithDelimiters(str, n) 

ゼロ幅マッチの正規表現については以下を参照してください。

blog1.mammb.com


StringBuilder.repeat

Java11 で String.repeat(int count) が追加されたのと同様に、StringBuilderStringBuffer にも repeat() が追加されました。

public StringBuilder repeat(int codePoint, int count) { ... }
public StringBuilder repeat(CharSequence cs, int count) { ... }
public synchronized StringBuffer repeat(int codePoint, int count) { ... }
public synchronized StringBuffer repeat(CharSequence cs, int count) { ... }

以下のように利用できます。

var sb = new StringBuilder();
sb.repeat('*', 10);


Unicode 絵文字プロパティ

java.lang.Character に絵文字プロパティを取得するメソッドが追加されました。

Character.isEmoji("😊".codePointAt(0)); // -> true 

その他、isEmojiPresentation(int codePoint) isEmojiModifier(int codePoint) isEmojiModifierBase(int codePoint) isEmojiComponent(int codePoint) isExtendedPictographic(int codePoint) も同じです。

正規表現のクラスについても利用可能です。

Pattern.compile("\\p{IsEmoji}").matcher("..");

詳細は以下を参照してください。

blog1.mammb.com

ただ、0-9#* のような文字もUnicode上は絵文字のカテゴリになるので注意点が必要です(emoji keycap sequence で、他の文字と組み合わせて絵文字を構成するため)。

Character.isEmoji("*".codePointAt(0)); // -> true 


HttpClient のクローズ処理

Java 11 で導入された java.net.http.HttpClient に以下のクローズ処理がAPIとして追加されました。

  • void close()
  • void shutdown()
  • void shutdownNow()
  • boolean awaitTermination(Duration duration)
  • boolean isTerminated()

合わせて AutoCloseable を実装するようになりました。

public abstract class HttpClient implements AutoCloseable {
}

HttpClient は通常、それ自身で接続プールを管理しているため、インスタンス生成とcloseを繰り返す使い方はせず、アプリケーション実行中は同じインスタンスを使うため、あまり困りませんでしたが、都合により頻繁にインスタンス生成を行う必要がある場合に(どういう状況?) close() によりリソースの解放を促進できるようになりました。


JFR.View コマンド

JFR(Java Flight Recorder) ツールに view コマンドが追加されました。 レコードファイルのダンプやイベント データの集計を簡単に表示することができます。

-XX:StartFlightRecording オプション、または JFR.start でJFRを有効にし、ビューを指定して、例えば以下のように JDK Mission Control などを起動することなく、イベントデータを確認できます。

$ jcmd <pid> JFR.start
$ jcmd <pid> JFR.view gc

                                Garbage Collections

Start    GC ID Type                     Heap Before GC Heap After GC Longest Pause
-------- ----- ------------------------ -------------- ------------- -------------
00:00:00     2 Young Garbage Collection       149.3 MB       17.5 MB       5.63 ms
00:00:00     3 Young Garbage Collection       157.5 MB       17.3 MB       4.12 ms
00:00:00     4 Young Garbage Collection       157.3 MB       17.8 MB       4.46 ms
00:00:00     5 Young Garbage Collection       157.8 MB       17.4 MB       4.06 ms
...

JFR.start のオプションには以下があります。

Options:

 cell-height   (Optional) Maximum number of rows in a table cell. (INTEGER, no default value)

 maxage        (Optional) Length of time for the view to span. (INTEGER followed by
               's' for seconds 'm' for minutes or 'h' for hours, default value is 10m)

 maxsize       (Optional) Maximum size for the view to span in bytes if one of
               the following suffixes is not used: 'm' or 'M' for megabytes OR
               'g' or 'G' for gigabytes. (STRING, default value is 32MB)

 truncate      (Optional) How to truncate content that exceeds space in a table cell.
               Mode can be 'beginning' or 'end'. (STRING, default value 'end')

 verbose       (Optional) Displays the query that makes up the view.
               (BOOLEAN, default value false)

 <view>        (Mandatory) Name of the view or event type to display.
               See list below for available views. (STRING, no default value)

 width         (Optional) The width of the view in characters
               (INTEGER, no default value)

Java virtual machine views:
 class-modifications       gc-concurrent-phases longest-compilations
 compiler-configuration    gc-configuration     native-memory-committed
 compiler-phases           gc-cpu-time          native-memory-reserved
 compiler-statistics       gc-pause-phases      safepoints
 deoptimizations-by-reason gc-pauses            tlabs
 deoptimizations-by-site   gc-references        vm-operations
 gc                        heap-configuration

Environment views:
 active-recordings        cpu-information       jvm-flags
 active-settings          cpu-load              native-libraries
 container-configuration  cpu-load-samples      network-utilization
 container-cpu-throttling cpu-tsc               recording
 container-cpu-usage      environment-variables system-information
 container-io-usage       events-by-count       system-processes
 container-memory-usage   events-by-name        system-properties

Application views:
 allocation-by-class   exception-count       native-methods
 allocation-by-site    file-reads-by-path    object-statistics
 allocation-by-thread  file-writes-by-path   pinned-threads
 class-loaders         finalizers            socket-reads-by-host
 contention-by-address hot-methods           socket-writes-by-host
 contention-by-class   latencies-by-type     thread-allocation
 contention-by-site    longest-class-loading thread-count
 contention-by-thread  memory-leaks-by-class thread-cpu-load
 exception-by-message  memory-leaks-by-site  thread-start
 exception-by-site     modules


 The <view> parameter can be an event type name. Use the 'JFR.view types'
 to see a list. To display all views, use 'JFR.view all-views'. To display
 all events, use 'JFR.view all-events'.

Example usage:

 $ jcmd <pid> JFR.view gc

 $ jcmd <pid> JFR.view width=160 hot-methods

 $ jcmd <pid> JFR.view verbose=true allocation-by-class

 $ jcmd <pid> JFR.view contention-by-site

 $ jcmd <pid> JFR.view jdk.GarbageCollection

 $ jcmd <pid> JFR.view cell-height=5 ThreadStart

 $ jcmd <pid> JFR.view truncate=beginning SystemProcess