
JEP 外の JDK 21 における変更点を、開発時に覚えておきたいものに絞りまとめておきます。
- Math.clamp() メソッドの追加
- 範囲指定可能な String.indexOf()
- 区切り文字を含めて分割する String.splitWithDelimiters()
- StringBuilder.repeat
- Unicode 絵文字プロパティ
- HttpClient のクローズ処理
- JFR.View コマンド
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)
ゼロ幅マッチの正規表現については以下を参照してください。
StringBuilder.repeat
Java11 で String.repeat(int count) が追加されたのと同様に、StringBuilderと StringBuffer にも 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("..");
詳細は以下を参照してください。
ただ、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