Java 26(JDK 26)は2026年3月17日にGA(一般提供)となった非LTSのフィーチャーリリースです。含まれるJEPは10本で、正式機能が5本、プレビューが4本、インキュベーターが1本です。OracleのPremier Supportは2026年9月で終わり、最後の更新は2026年8月18日の26.0.2.1でした。2026年9月15日にはJava 27が出ています。
この記事では、Java 26で入ったJEPの中身と既定値の変更を、Temurin 26.0.2.1で実際に動かした出力つきで整理します。そのうえで、26を使っている環境がいまどこへ移るべきかを判断できるようにします。各版のサポート期限と最新版の一覧はOpenJDKは商用利用できる?無料の範囲とOracle JDKとの違い・ライセンス・サポート期限【2026年最新】にまとめています。
まとめ:Java 26の要点と今から取る対応
- Java 26はLTSではありません。OracleのPremier Supportは2026年9月で終了し、Extended Supportはありません。Oracleは26.0.2.1について、2026年10月20日のCPU以降は使わないよう案内しています。26.0.3は出ていません。
- 正式機能のうち、コードに影響が出やすいのは2つです。リフレクションでfinalフィールドを書き換えると警告が出るようになったこと(JEP 500)と、Applet APIが削除されたこと(JEP 504)です。
- 性能や通信に関わる正式機能は3つです。HTTP/3対応(JEP 517、クライアントかリクエストのコードで指定が必要)、ZGCでもAOTキャッシュの事前生成オブジェクトが読まれるようになったこと(JEP 516)、G1のスループット改善(JEP 522)です。初期ヒープの既定値もJEPの外で変わりました。
- プレビュー4本はまだ正式化していません。Java 27でも構造化並行性・Lazy Constants・プリミティブ型パターンはプレビューのままです。2026年10月7日更新のJDK 28のページでは、構造化並行性(JEP 543)が搭載の提案中、PEM(JEP 542)が正式化の対象として掲載されています。
- いま26で動いている本番は、Java 25 LTSへ戻すか27へ進めるかを決める時期です。26固有のAPIへの依存がなく、アプリと依存ライブラリの25対応を確認できるなら、25 LTSへの移行を優先してください。
Java 26の10個のJEP一覧とサポート期限
JDK 26のプロジェクトページに載っているJEPは次の10本です。区分は正式・プレビュー・インキュベーターの3つで、本番で既定のまま使えるのは正式の5本だけです。
正式5本・プレビュー4本・インキュベーター1本のJEP一覧
| JEP | 内容 | 区分 |
|---|---|---|
| 500 | finalフィールド変更への警告(Prepare to Make Final Mean Final) | 正式 |
| 504 | Applet APIの削除 | 正式 |
| 516 | 任意のGCで使えるAOTオブジェクトキャッシュ | 正式 |
| 517 | HTTP ClientのHTTP/3対応 | 正式 |
| 522 | G1 GCの同期削減によるスループット改善 | 正式 |
| 524 | 暗号オブジェクトのPEMエンコーディング | 第2プレビュー |
| 525 | 構造化並行性(Structured Concurrency) | 第6プレビュー |
| 526 | Lazy Constants | 第2プレビュー |
| 529 | Vector API | 第11インキュベーター |
| 530 | プリミティブ型のパターン(instanceof・switch) | 第4プレビュー |
JEP(JDK Enhancement Proposal)は、OpenJDKで一定規模以上の変更を提案・追跡するための文書です。番号は提案順に振られるので、版ごとに並んでいるわけではありません。たとえば検索でよく見かけるJEP 527(TLS 1.3の耐量子ハイブリッド鍵交換)はJava 27の機能で、26には入っていません。
Java 26はLTSではない|Premier Supportと26.0.xの更新日程
Oracle Java SE Support Roadmapでは、26は「non-LTS」と書かれ、GAは2026年3月、Premier Supportは2026年9月まで、Extended Supportは「Not Available」です。LTSは8・11・17・21・25で、次のLTSは2027年9月予定のJava 29です。「java 26 lts」と検索されることがありますが、26はLTSではありません。
| 版 | 公開日 | 種類 |
|---|---|---|
| 26(GA) | 2026-03-17 | 機能リリース |
| 26.0.1 | 2026-04-21 | 四半期CPU |
| 26.0.2 | 2026-07-21 | 四半期CPU |
| 26.0.2.1 | 2026-08-18 | CSPU(月次の追加更新) |
26.0.2.1のリリースノートには、2026年10月20日に予定されている次のCPUの後は、この版を使わないよう書かれています。jdk26uリポジトリのタグも26.0.2.1で止まっていて、「java26.3」に当たる26.0.3はありません。Temurinの配布も26.0.2.1が最後です。
正式化された5つのJEPの挙動と影響範囲
以下の出力は、macOS(x64、Core i9-9880H、物理メモリ16GB)にTemurin 26.0.2.1+1と25.0.4.1+1を入れて、記事作成時に実行したものです。
JEP 500:finalフィールドの書き換え警告と4つのモード
リフレクションのField.setでfinalフィールドを書き換えると、JDK 26からは警告が出ます。Java 25までは何も出ずに書き換わっていました。
import java.lang.reflect.Field;
public class FinalMut {
static class Config {
final String host;
Config() { host = "localhost"; }
}
public static void main(String[] args) throws Exception {
Config c = new Config();
Field f = Config.class.getDeclaredField("host");
f.setAccessible(true);
f.set(c, "example.com"); // finalフィールドをリフレクションで書き換える
System.out.println("host=" + c.host);
}
}
$ java FinalMut.java
WARNING: Final field host in class FinalMut$Config has been mutated reflectively by class FinalMut in unnamed module @5f8edcc5 (file:/private/tmp/j26/FinalMut.java)
WARNING: Use --enable-final-field-mutation=ALL-UNNAMED to avoid a warning
WARNING: Mutating final fields will be blocked in a future release unless final field mutation is enabled
host=example.com
$ java --illegal-final-field-mutation=deny FinalMut.java
Exception in thread "main" java.lang.IllegalAccessException: class FinalMut (in unnamed module @7b02881e) cannot set final field FinalMut$Config.host (in unnamed module @7b02881e), unnamed module @7b02881e is not allowed to mutate final fields
警告の出し方は--illegal-final-field-mutationで切り替えます。Oracleの移行ガイドによると、warnが既定で、モジュールごとに最初の1回だけ警告します。
| 値 | 挙動 |
|---|---|
| allow | 警告なしで許可(25までと同じ) |
| warn(既定) | モジュールごとに初回だけ警告 |
| debug | 書き換えのたびに警告とスタックトレース |
| deny | IllegalAccessExceptionで拒否 |
正当な理由があって書き換える場合は、--enable-final-field-mutation=ALL-UNNAMED(クラスパス上のコード)か、モジュール名をカンマ区切りで渡して許可します。実機でもこの指定で警告が消えました。対応の順番としては、まずCIをdenyで回します。そこで落ちた箇所が、将来の版で動かなくなる場所です。依存ライブラリの中で落ちた場合は、ライブラリの更新で解消するかどうかを先に確かめ、許可フラグは最後の手段にしてください。
JEP 504:Applet API削除後のコンパイルエラーと–release 25の落とし穴
削除されたのはjava.appletパッケージ全体、javax.swing.JApplet、java.beans.AppletInitializerなどのアプレット関連APIです。Swing・AWT本体は残っています(詳しくはJava Swingとは?廃止されたのはアプレットAPIだけ|AWTとの違いと使い方)。
$ javac AppletUse.java # JDK 26
AppletUse.java:1: error: package java.applet does not exist
import java.applet.Applet;
$ javac --release 25 -d out AppletUse.java RunApplet.java # JDK 26のjavacで25向けにビルド
AppletUse.java:2: warning: [removal] Applet in java.applet has been deprecated and marked for removal
$ java -cp out RunApplet # そのままJDK 26で実行
Exception in thread "main" java.lang.NoClassDefFoundError: java/applet/Applet
見落としやすいのが2つ目の例です。JDK 26のjavacでも--release 25を付けると、警告だけでコンパイルは通ります。ところが、そのクラスを26のJVMで動かすとNoClassDefFoundErrorで止まります。ビルドの成功だけで判定せず、26の実行環境でテストを回してください。
JEP 517:HTTP/3を使うHttpClientの書き方と1回目がHTTP/2になる挙動
HTTP/3は既定では選ばれません。HttpClient.BuilderかHttpRequest.BuilderのversionにHTTP_3を指定したときだけ使われます。次のコードは検証に使ったプログラムの抜粋で、出力の後半2行は、HTTP_3_URI_ONLYを付けたリクエストと、バージョンを指定しないクライアントで別に送った結果です。
var client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_3) // 既定はHTTP/2のまま。明示が必要
.build();
var req = HttpRequest.newBuilder(URI.create("https://www.cloudflare.com/")).GET().build();
for (int i = 0; i < 2; i++) {
var res = client.send(req, HttpResponse.BodyHandlers.discarding());
System.out.println("try" + i + ": " + res.version() + " " + res.statusCode());
}
// HTTP/3以外を許さない場合はリクエストにH3_DISCOVERYを付ける
var strict = HttpRequest.newBuilder(URI.create("https://www.cloudflare.com/"))
.setOption(HttpOption.H3_DISCOVERY, HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY)
.GET().build();
try0: HTTP_2 200
try1: HTTP_3 200
HTTP_3_URI_ONLY: HTTP_3 200
バージョン指定なしのクライアント: HTTP_2
Cloudflareとgoogle.comに同じコードを当てたところ、どちらも1回目はHTTP/2、同じクライアントの2回目からHTTP/3になりました。この順序は接続先やネットワーク条件によって変わります。H3_DISCOVERYを指定しないと、既定のANYモードで動きます。このモードでは、QUICとTCPの両方で接続を試してよい実装依存の方式になっています。そのため、ベンチマークで初回リクエストを測るとHTTP/2の数値が混ざります。HTTP_3_URI_ONLYを指定するとHTTP/2やHTTP/1.1には戻らず、相手がHTTP/3に対応していなければ失敗します。JDK 26のHttpClientはプロキシ経由のHTTP/3をサポートしません。HTTP/3を有効にしてHTTP_3_URI_ONLYを指定した要求は、プロキシが選択されると失敗します。それ以外のモードでは、プロキシを使う時点でHTTP/2かHTTP/1.1に下がります。
JEP 516:ZGCでもAOTキャッシュのオブジェクトが読まれる条件と実行時間の実測
Java 24で入ったAOTキャッシュ(JEP 483)は、事前に生成したJavaオブジェクトをGC固有の形式でメモリに直接マップしていました。そのため、ZGCではこのオブジェクトが使えませんでした。JEP 516では、GCに依存しない形式から順にストリームで読み込む方式が加わりました。
# 1. 訓練実行:本番と同じGC・同じヒープ上限で1回走らせ、キャッシュを書き出す
java -XX:+UseZGC -XX:AOTCacheOutput=app.aot -cp app.jar App
# 2. 本番起動:キャッシュを指定する
java -XX:+UseZGC -XX:AOTCache=app.aot -cp app.jar App
# キャッシュから事前生成オブジェクトが読まれたかはログの (Heap) 行で分かる
java -XX:+UseZGC -XX:AOTCache=app.aot -Xlog:aot -cp app.jar App | grep "(Heap)"
ZGCで訓練したキャッシュをZGCで起動したところ、JDK 25のログには(Heap)領域が1行も出ませんでしたが、JDK 26ではMapped static region #3 ... (Heap)が出ました。小さなサンプル(コレクション集計・仮想スレッド・HttpClient生成)を12回実行し、最初の2回を除いた10回について、プロセス起動から終了までの経過時間の中央値を求めました。
| 版・GC | キャッシュなし | キャッシュあり |
|---|---|---|
| JDK 25・ZGC | 951ms | 769ms |
| JDK 26・ZGC | 1,052ms | 639ms |
| JDK 26・G1 | 1,042ms | 650ms |
ZGCで比べると、キャッシュの効き目は25で約19%、26で約39%でした。同じ手順の1回目の計測では、25・ZGCのキャッシュなしが1,365ms、ありが938msで、回によって数百ms動きました。どちらの回も26・ZGCのキャッシュあり(658ms・639ms)が25より速く出ていますが、負荷のかかった開発機での小さなサンプルの値です。自分のアプリで測り直してください。
実務で引っかかるのは訓練側のGC設定です。既定のG1(圧縮oopsが有効)で作ったキャッシュをZGCの本番で指定すると、次のように丸ごと無効になります。
$ java -XX:+UseZGC -XX:AOTCache=app-g1.aot -cp app.jar App # 既定のG1で作ったキャッシュ
[0.008s][warning][aot] Unable to use AOT cache.
[ ] The saved state of UseCompressedOops and UseCompressedClassPointers is different from runtime, CDS will be disabled.
JEPは-XX:+AOTStreamableObjectsでGC非依存形式を強制できると説明しています。ただし26.0.2.1ではこれは診断用フラグで、-XX:+UnlockDiagnosticVMOptionsが要りました。付けてG1で訓練しても、ZGCでは同じエラーで読めませんでした。一方、G1でも-Xmx40gで圧縮oopsが無効の状態で訓練したキャッシュは、ZGCで(Heap)まで読めました。圧縮oopsの有無が一致するかどうかが分かれ目です。訓練は本番と同じGCとヒープ上限で行うのが確実です。ZGCそのものの仕組みはZGCとは?Javaの低遅延GCの仕組みとG1GCとの違い・有効化手順をJDK 25の実測で解説で扱っています。
JEP 522:G1の書き込みバリア短縮とスループット5〜15%の条件
G1は、アプリのスレッドが参照フィールドを書き換えるたびに書き込みバリアを実行し、GCスレッドと同期していました。JEP 522ではカードテーブルを2枚に分け、この同期を減らしています。JEPによると、x64の書き込みバリアは約50命令から12命令に減りました。参照フィールドを頻繁に書き換えるアプリでは5〜15%、そうでないアプリでも最大5%のスループット向上が観測されています。設定の変更は要りません。GCログの見え方も変わらないため、効果は同じ負荷で25と26のスループットを並べて測るしかありません。
JEP外の既定値変更|初期ヒープの最小ヒープサイズへの統一
JDK 26では、-Xmsを指定しないときの初期ヒープの決め方も変わりました。JEPではなく、CSR(JDK-8371987)で承認された変更です。以前は物理メモリの1/64(InitialRAMPercentage=1.5625)を初期ヒープにしていましたが、26ではこの既定値がなくなり、初期ヒープはMinHeapSizeと同じになります。
$ java -XX:+PrintFlagsFinal -version | grep -E " (InitialHeapSize|InitialRAMPercentage) "
# JDK 25.0.4.1(物理メモリ16GB)
size_t InitialHeapSize = 268435456 {product} {ergonomic}
double InitialRAMPercentage = 1.562500 {product} {default}
# JDK 26.0.2.1(同じマシン)
size_t InitialHeapSize = 8388608 {product} {ergonomic}
double InitialRAMPercentage = 0.000000 {product} {default}
同じ16GBのマシンで、初期ヒープは256MBから8MBに減りました。起動は軽くなりますが、立ち上がり直後に大量のオブジェクトを作るアプリでは、ヒープを広げるGCが序盤に増えます。OpenJDKのバグ管理には、この変更の前段(JDK-8348278)が原因とされるベンチマーク低下の報告が複数登録されています。コンテナで-Xmsを省略して25の挙動に頼っていた場合は、-Xmsか-XX:InitialRAMPercentage=1.5625を明示すると25と同じ値に戻せます(実機で268435456バイトに戻ることを確認しました)。
プレビュー4本とインキュベーターの書き方とJava 27・28でのその後
プレビュー機能は--enable-previewを付けないとコンパイルも実行もできません。版をまたぐとAPIが変わるので、本番コードに入れるとJDKの更新が止まりやすくなります。26で試した4本と、その後の版での扱いは次のとおりです。
| 機能 | JDK 26 | JDK 27(2026-09) | JDK 28(2027-03予定) |
|---|---|---|---|
| 構造化並行性 | JEP 525 第6プレビュー | JEP 533 第7プレビュー | JEP 543 正式化を提案中 |
| Lazy Constants | JEP 526 第2プレビュー | JEP 531 第3プレビュー | 未掲載(2026-10-07時点) |
| プリミティブ型パターン | JEP 530 第4プレビュー | JEP 532 第5プレビュー | 未掲載 |
| PEMエンコーディング | JEP 524 第2プレビュー | JEP 538 第3プレビュー | JEP 542 正式化(対象に決定) |
| Vector API | JEP 529 第11インキュベーター | JEP 537 第12インキュベーター | 未掲載 |
JEP 526:StableValueからLazyConstantへの改名とList.ofLazy
Java 25のStableValue(JEP 502)は、26でLazyConstantに名前が変わりました。trySet・setOrThrow・orElseSetのように外から値を入れるメソッドはなくなり、計算関数を渡すLazyConstant.ofだけが残っています。計算結果にnullは使えません。JDK 26ではjava.lang.StableValue自体が存在しないので、25向けに書いたプレビューコードはそのままでは動きません。
import java.util.List;
public class Lazy {
static final LazyConstant<String> GREETING =
LazyConstant.of(() -> { System.out.println("init!"); return "hello"; });
static final List<Integer> SQUARES =
List.ofLazy(5, i -> { System.out.println("compute " + i); return i * i; });
public static void main(String[] args) {
System.out.println("start");
System.out.println(GREETING.get());
System.out.println(GREETING.get());
System.out.println(SQUARES.get(3));
System.out.println(SQUARES.get(3));
}
}
$ java --enable-preview Lazy.java
start
init!
hello
hello
compute 3
9
9
「init!」は最初のget()で1回だけ出ます。List.ofLazyは、触った要素だけを計算します。設定値の読み込みやロガーの生成のように、起動時に全部作る必要がないものを後回しにする用途に向いています。
JEP 525:構造化並行性の第6プレビューで変わったJoiner
構造化並行性は、複数の子タスクをひとまとまりとして起動・待機・中断する仕組みです。仮想スレッドと組み合わせて使う前提の設計です(仮想スレッドの仕組みはJava 仮想スレッドとは?プラットフォームスレッドとの違い・仕組みと効く処理を実測で解説)。
import java.time.Duration;
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.StructuredTaskScope.Joiner;
// 2つの処理を並行に走らせ、両方の成功を待つ。500msでキャンセルを要求する。
// close()は子タスクの終了を待つため、割り込みに応答しない処理は500msで終了しない。
try (var scope = StructuredTaskScope.open(Joiner.<String>allSuccessfulOrThrow(),
cf -> cf.withTimeout(Duration.ofMillis(500)))) {
var user = scope.fork(() -> fetch("user", 100));
var order = scope.fork(() -> fetch("order", 200));
scope.join(); // 期限切れなら StructuredTaskScope.TimeoutException
System.out.println(user.get() + "," + order.get());
}
25と26のJoinerの変更のうち、ここでは次の3点を取り上げます。allSuccessfulOrThrow()で生成したJoinerを使うスコープのjoin()の戻り値がStream<Subtask<T>>からList<T>になったこと、anySuccessfulResultOrThrow()がanySuccessfulOrThrow()に改名されたこと、タイムアウト時に呼ばれるonTimeout()が加わったことです。上のコードで子タスクを1,000ms待たせ、期限を150msにすると、StructuredTaskScope$TimeoutExceptionが発生しました。27の第7プレビューでもAPIは変わっています。正式版を待つなら、28のJEP 543の行方を見てから書き直すほうが手戻りは少なく済みます。
JEP 530:プリミティブ型パターンでswitchとinstanceofに書ける範囲
switchやinstanceofのパターンに、byteやintなどのプリミティブ型を書けるようになります。値の範囲に収まるかどうか(情報を失わずに変換できるか)で一致が決まります。
static String classify(int v) {
return switch (v) {
case byte b -> "fits in byte: " + b;
case short s -> "fits in short: " + s;
case int i -> "int: " + i;
};
}
// classify(100) -> fits in byte: 100
// classify(1000) -> fits in short: 1000
// classify(100000) -> int: 100000
double d = 42.0;
if (d instanceof int n) { ... } // 情報を失わずintへ変換できるときだけ一致(42.5なら false)
--enable-previewを付けずにコンパイルすると「primitive patterns are a preview feature and are disabled by default」で止まります。27でも第5プレビューのままです。
JEP 524のPEMとJEP 529のVector APIの位置づけ
PEMは、鍵や証明書をPEM形式で読み書きするAPIです。26の第2プレビューではPEMRecordがPEMに改名され、Base64を復号するdecode()が加わりました。JDK 28のページに正式化(JEP 542)が対象として掲載されているので、BouncyCastleなどの外部ライブラリから切り替えるなら28を待つのが筋です。Vector APIは26でも「大きな変更なし」で再インキュベーションになりました。JEPには、Project Valhallaの必要な機能がプレビューになるまでインキュベーションを続けると書かれています。28で値オブジェクト(JEP 401)がプレビューの対象になったことが、次の動きの手がかりです。
Java 26を使っている環境の移行先と判断基準
Oracle JDK 26のPremier Supportは終了しています。26で動いている環境は、利用中の配布元の更新方針を確認したうえで、Java 25 LTSに戻すか、27に進めるかを決める必要があります。判断の軸は、プレビューAPIを使っているかどうかと、半年ごとにJDKを入れ替える体制があるかどうかです。
Java 25 LTSへ戻すべき環境と、戻すときに失うもの
25 LTSへの移行を勧めるのは、26で追加されたAPIに依存せず、アプリと依存ライブラリを25対応のクラスファイルで用意でき、25上で回帰テストを通せる業務システムです。25はOracleのPremier Supportが2030年9月まであります。戻すときに失うものは、ZGCでのAOTキャッシュの効果(JEP 516)、HTTP/3、G1の書き込みバリア改善の3つです。JEP 500の警告は25では出ませんが、書き換えている箇所は26のCIで洗い出せているはずなので、そのリストを残しておくと29 LTSへの移行で役立ちます。LazyConstantを使っている場合、25のStableValueとはAPIが違うため、戻すには書き直しが必要です。古い版から一気に上げる手順はJava近代化の進め方|Java 8をJava 25へ上げる判断基準と4ステップを参照してください。
Java 27へ進めてよい環境の条件
27に進めてよいのは、2027年3月の28 GAに合わせてもう一度JDKを入れ替える工数を確保でき、CIで回帰テストを自動で回せる案件です。27ではG1がすべての環境で既定のGCになり、コンパクトオブジェクトヘッダも既定で有効になりました。コードを変えなくても挙動が変わる点は26以上に多いです。詳しくはJava 27とは|非LTSの半年運用とG1・オブジェクトヘッダ既定化の影響で扱っています。ビルドツールは、Gradleの互換表でJava 26のツールチェーンとGradle本体の実行は9.4.0から、Java 27は9.8.0からサポートされています。
検証用にJava 26を入手してバージョンを確かめる手順
プレビュー機能や挙動の差を確かめるために26を入れる場合は、26.0.2.1は、Adoptium(Eclipse Temurin)の公式リリースから取得します。Oracle JDK 26の配布もありますが、更新は止まっています。展開後にjava -versionで版を確認してください。
$ java -version
openjdk version "26.0.2.1" 2026-08-18
OpenJDK Runtime Environment Temurin-26.0.2.1+1 (build 26.0.2.1+1)
OpenJDK 64-Bit Server VM Temurin-26.0.2.1+1 (build 26.0.2.1+1, mixed mode)
本番には置かず、CIのマトリクスか開発機の検証用にとどめてください。複数の版を並べて同じコードを流すと、この記事の各節のような差がそのまま見えます。
よくある質問
Java 26はLTSですか?
LTSではありません。OracleのロードマップでJava 26は非LTSで、Premier Supportは2026年9月まで、Extended Supportはありません。LTSは25の次が2027年9月予定のJava 29です。
Java 26のサポートはいつまでですか?
OracleのPremier Supportは2026年9月までです。最後の更新は2026年8月18日の26.0.2.1で、Oracleは2026年10月20日のCPU以降はこの版を使わないよう案内しています。
Java 26.0.3は出ますか?
2026年10月8日時点で、jdk26uのタグとTemurinの配布はどちらも26.0.2.1が最後です。Premier Supportが終わっているので、26の更新を待つより25 LTSか27へ移ってください。
Java 26でfinalフィールドを書き換えるライブラリは動かなくなりますか?
従来から変更可能だった通常クラスの非staticなfinalフィールドは、アクセス条件を満たせば、26の既定のwarnモードでも警告付きで変更できます。static finalのフィールドと、recordやhidden classのfinalフィールドは、26より前からリフレクションでも書き換えられず、IllegalAccessExceptionになります。将来の版で既定が拒否に変わる予定なので、--illegal-final-field-mutation=denyでCIを回して影響箇所を先に見つけてください。
Java 26でStructured ConcurrencyやLazy Constantsは正式版ですか?
どちらもプレビューで、使うには--enable-previewが必要です。27でもプレビューのままで、構造化並行性は28でJEP 543として正式化が提案されている段階です。