2026年3月リリースのJava 26で開発者が押さえるべき10個のJEPと全体像
目次
- 1 2026年3月リリースのJava 26で開発者が押さえるべき10個のJEPと全体像
- 2 正式導入された5つのJEPがもたらす起動性能・GC・HTTP通信の具体的改善
- 3 AOTキャッシュとG1 GC同期削減で実現するスループット5〜15%向上の仕組み
- 4 Lazy ConstantsやStructured Concurrencyなどプレビュー機能4本の変更点と将来展望
- 5 finalフィールド変更警告とApplet API廃止が既存コードに与える影響と対処手順
- 6 非LTS版Java 26をJDK 25 LTSと併用する際の判断基準と運用上の注意点
- 7 Spring Boot・Hibernate環境でJava 26を導入する際のCI設定と依存関係チェックリスト
2026年3月リリースのJava 26で開発者が押さえるべき10個のJEPと全体像
Java 26(JDK 26)は2026年3月17日に正式リリースされました。半年ごとの定期リリースサイクルに基づく非LTS(Long-Term Support)バージョンであり、2025年9月に公開されたJDK 25 LTSの次のフィーチャーリリースにあたります。今回のリリースには合計10本のJEP(JDK Enhancement Proposal)が含まれており、起動性能の改善やGCの最適化、HTTP/3対応といった実用的な強化が中心です。新しい言語構文が正式化されたわけではありませんが、ランタイム層とライブラリ層で堅実な改善が積み重ねられています。ここではJava 26の全体像を理解するために、各JEPの分類やプロジェクトとの関係、エコシステムの最新動向を整理します。
半年サイクルで届くJDK 26の位置づけとJDK 25 LTSとの役割分担
Javaは2017年のJava 9以降、半年に1回の定期リリースサイクルを採用しています。このサイクルのなかでLTS版は数年に一度指定され、企業の本番環境で長期間利用されることを前提としたサポートが提供されます。直近のLTSであるJDK 25は2025年9月にリリースされ、Oracle Premier Supportでは2033年9月まで無償アップデートが予定されています。一方、JDK 26は非LTSであり、Premier Supportの期間は6か月にとどまります。
この位置づけから、JDK 26は本番環境で即座に全面採用するリリースというよりも、次期LTSに向けた機能のプレビュー検証や、ランタイム改善の早期享受を目的として活用するのが一般的です。JDK 25 LTSを本番で維持しつつ、CI環境やステージング環境でJDK 26を並行検証するアプローチが多くのチームにとって合理的な選択となります。非LTS版を毎回追いかける必要はありませんが、半年ごとに蓄積される改善を把握しておくことで、次期LTSへの移行をスムーズに進められます。
正式5本・プレビュー4本・インキュベーター1本で構成されるJEP分類一覧
Java 26に含まれる10本のJEPは、正式機能(Final)が5本、プレビュー機能が4本、インキュベーター機能が1本という構成です。正式機能はそのまま本番コードで利用でき、プレビュー機能はコンパイル時・実行時に--enable-previewフラグの指定が必要です。インキュベーター機能は実験的なAPIであり、--add-modulesによる明示的なモジュール追加が求められます。
| JEP番号 | 機能名 | ステータス | カテゴリ |
|---|---|---|---|
| JEP 500 | Prepare to Make Final Mean Final | Final | Java言語仕様 |
| JEP 504 | Remove the Applet API | Final | クライアントライブラリ |
| JEP 516 | Ahead-of-Time Object Caching with Any GC | Final | HotSpot |
| JEP 517 | HTTP/3 for the HTTP Client API | Final | コアライブラリ |
| JEP 522 | G1 GC: Improve Throughput by Reducing Synchronization | Final | HotSpot |
| JEP 524 | PEM Encodings of Cryptographic Objects | 2nd Preview | セキュリティライブラリ |
| JEP 525 | Structured Concurrency | 6th Preview | コアライブラリ |
| JEP 526 | Lazy Constants | 2nd Preview | コアライブラリ |
| JEP 529 | Vector API | 11th Incubator | コアライブラリ |
| JEP 530 | Primitive Types in Patterns, instanceof, and switch | 4th Preview | Java言語仕様 |
前回のJDK 25では18本のJEPが搭載されていたのに対し、JDK 26は10本と比較的少数です。これは新規言語機能の正式化が今回見送られ、パフォーマンス改善やAPI成熟に重点が置かれたためです。
Project Leyden・Loom・Amberなど5大プロジェクトとの対応関係
OpenJDKでは長期的な技術ビジョンを複数のプロジェクトとして推進しており、各JEPはいずれかのプロジェクトに紐づいています。Java 26のJEPを5大プロジェクトの観点から整理すると、全体の方向性がより明確になります。Project Leydenは起動性能とウォームアップ時間の改善を目指すプロジェクトで、JEP 516(AOTオブジェクトキャッシュ)がここに該当します。Java 24のJEP 483から始まったAOTキャッシュの改善が、Java 26でGC非依存化を達成した形です。
Project Loomは軽量な並行処理モデルの実現を掲げており、JEP 525(Structured Concurrency)が6回目のプレビューとして引き続き成熟を進めています。Project Amberは言語の表現力向上を担当し、JEP 530(プリミティブ型パターンマッチング)が4回目のプレビューに達しています。Project Panamaはネイティブコード連携を扱いますが、Java 26ではJEPの追加はありません。Project Valhallaは値型の導入を目指す長期プロジェクトで、JEP 529(Vector API)がValhalla完成待ちのままインキュベーターに留まっています。このように各プロジェクトの進捗状況がJEPのステータスに直接反映されています。
Java 24〜25で導入済みの機能がJava 26で到達したステータス変遷
Java 26の機能を理解するうえで、過去バージョンからの変遷を把握しておくことが重要です。AOTキャッシュはJava 24でJEP 483として初めて導入され、Java 25ではJEP 514でキャッシュ生成のコマンドライン操作が簡素化されるとともに、JEP 515でメソッドプロファイリング情報のキャッシュ保存が追加されました。Java 26のJEP 516ではさらにGC非依存形式での保存が可能になり、ZGCユーザーにも恩恵が及ぶようになっています。この3段階の進化はProject Leydenのロードマップに沿った計画的な展開です。
Structured Concurrencyは最初のプレビューがJDK 19にまで遡り、6回のプレビューを経てAPI設計が安定してきました。Lazy ConstantsはJDK 25でStable Valuesとして初登場し、JDK 26ではLazyConstantへのリネームとAPIの大幅な簡素化が行われています。プリミティブ型パターンマッチングはJDK 23から3回のプレビューを経て4回目に到達しており、支配性チェックの強化が加えられました。Vector APIはJDK 16以来11回目のインキュベーションとなり、Valhalla由来の値型が利用可能になるまで正式化は保留されています。こうした経緯を踏まえると、Java 26は大きな新機能の投入よりも、既存機能の成熟と基盤強化に注力したリリースであることが分かります。
JavaOne 2026同時発表のJava Verified Portfolioが示すエコシステム拡張の方向性
Java 26のリリースに合わせ、2026年3月17〜19日にカリフォルニア州レッドウッドショアーズでJavaOne 2026カンファレンスが開催されました。Oracleはこの場でJava Verified Portfolio(JVP)という新たな取り組みを発表しています。JVPはOracleがサポートするツール、フレームワーク、ライブラリ、サービスを厳選して提供するポートフォリオで、JavaFXとHelidonの商用サポートが含まれています。
Helidonはマイクロサービス向けのJavaフレームワークであり、OracleはHelidonのリリースサイクルをJavaのリリースサイクルと同期させる意向を示しています。さらにHelidonをOpenJDKプロジェクトとして提案する計画も公表されました。この動きはJavaプラットフォーム単体の進化にとどまらず、周辺エコシステムとの統合をより緊密にする方向性を示しています。エンタープライズ開発者にとっては、JDKのバージョンアップとフレームワークの互換性維持がより予測しやすくなる可能性があります。JVPの対象範囲が今後どこまで広がるかは、Javaエコシステム全体の発展に影響を与える重要なポイントです。
正式導入された5つのJEPがもたらす起動性能・GC・HTTP通信の具体的改善
Java 26で正式導入(Final)となった5本のJEPは、いずれもフラグ不要で即座に利用できる実用的な改善です。AOTキャッシュのGC非依存化、G1 GCのスループット向上、HTTP/3対応、finalフィールド変更に対する警告機構、そしてApplet APIの完全削除が含まれます。言語構文の変更こそありませんが、JDKをアップグレードするだけでアプリケーションの性能特性やセキュリティが改善される点で、開発者にとって即効性の高い内容です。
JEP 516によるAOTオブジェクトキャッシュがZGC対応で広がる適用範囲
JEP 516はProject Leydenの一環として、HotSpot JVMのAOT(Ahead-of-Time)キャッシュをすべてのガベージコレクタで利用可能にする改善です。Java 24で導入されたJEP 483ではAOTクラスローディングとリンキングが実現されましたが、キャッシュの保存形式が特定のGCに依存していたため、ZGC(Z Garbage Collector)のような低レイテンシGCでは利用できない制約がありました。Java 26ではキャッシュされたJavaオブジェクトをGC非依存のフォーマットで保存し、起動時にシーケンシャルにメモリへロードする方式に変更されています。
この改善により、ZGCを使用するアプリケーションでもAOTキャッシュの恩恵を受けられるようになりました。低レイテンシが求められるリアルタイムシステムやWebサーバーでは、ZGCの採用率が高い傾向にあるため、この対応は実用的な意味が大きいといえます。また、AOTキャッシュを生成したときと異なるGCで実行する場合にもキャッシュの再生成が不要になるため、開発環境と本番環境でGC設定が異なるケースでも運用がシンプルになります。
JEP 522のデュアルカードテーブル方式でG1 GCスループットが5〜15%改善する原理
JEP 522はJavaのデフォルトGCであるG1 GCのスループットとレイテンシを改善するJEPです。G1 GCはJava 9以降デフォルトGCとして採用されており、大きなヒープに対して高い性能と低い停止時間を両立することを目指しています。ただし、G1はアプリケーションスレッドと並行してGC処理を行うため、両者の間で同期が必要であり、この同期オーバーヘッドがスループット低下とレイテンシ増大の原因になっていました。
従来のG1 GCでは、アプリケーションスレッドとGCスレッドが単一のカードテーブルを共有していました。カードテーブルはヒープ内のオブジェクト参照変更を追跡するデータ構造で、オブジェクトの参照が書き換わるたびに更新されます。JEP 522ではこの構造をデュアルカードテーブルに変更し、アプリケーション側とGC側がそれぞれ独立したテーブルを持つようにしました。これにより書き込みバリアでの同期が不要になり、参照操作が多いワークロードで5〜15%のスループット向上が見込まれています。JDKをアップグレードするだけで追加設定なく自動的に恩恵を受けられる改善です。
JEP 517でHTTP/3を有効化する1行変更とHTTP/2自動フォールバックの挙動
JEP 517はJava 11で導入されたHTTP Client APIにHTTP/3プロトコルのサポートを追加するJEPです。HTTP/3はQUICプロトコル上で動作するHTTPの最新バージョンであり、ハンドシェイクの高速化、より信頼性の高いトランスポート、ネットワーク輻輳の回避などの利点があります。現在、主要なWebブラウザの大半と全Webサイトの約40%がHTTP/3に対応しており、サーバーサイドJavaアプリケーションからもHTTP/3でアクセスできる意義は大きいといえます。
HTTP/3を利用するためのコード変更は最小限です。HttpClient.newBuilder().version(HttpClient.Version.HTTP_3).build()のように、ビルダーでバージョンを指定するだけで有効化できます。サーバー側がHTTP/3に対応していない場合は自動的にHTTP/2へフォールバックするため、既存のコードとの互換性も維持されます。外部のQUICライブラリやNettyの追加設定は不要で、JDK標準の機能だけで完結します。デフォルトのプロトコルバージョンはHTTP/2のままであり、HTTP/3への切り替えは明示的なオプトイン方式を採用しています。
JEP 500がfinalフィールド変更を警告する4段階の制御オプション
JEP 500はJavaの将来のリリースでfinalフィールドの変更をデフォルトで禁止することを見据えた準備段階のJEPです。finalフィールドはコンストラクタまたはクラス初期化子で一度設定されたら変更されないことが言語仕様上の意図ですが、これまでディープリフレクションを使えば実行時にfinalフィールドを変更できてしまう状態でした。JEP 500ではこの変更が行われた際にJVMログに警告を出力するようになります。
制御には--illegal-final-field-mutationオプションが用意されており、allow(警告なしで変更を許可)、warn(デフォルト、初回変更時に警告を出力)、debug(警告に加えてスタックトレースも出力)、deny(変更を拒否しエラーとする)の4モードを選択できます。さらに--enable-final-field-mutation=M1,M2オプションを使えば、特定のモジュールに対してのみfinalフィールドの変更を許可することも可能です。将来的にはデフォルトがdenyに変更される予定で、その際にallowモードは廃止されますが、warnとdebugは少なくとも1リリースはサポートが継続されます。Java 26の段階で警告を確認し、影響範囲を把握しておくことが重要です。
JEP 504によるApplet API完全削除でビルドサイズとセキュリティが改善する理由
JEP 504はJDK 17で非推奨(deprecated for removal)となっていたApplet APIを完全に削除するJEPです。Applet APIはかつてWebブラウザ上でJavaアプリケーションを実行するために使われていましたが、現在のJDKリリースおよび現行のWebブラウザはいずれもアプレットをサポートしていません。使用されることもサポートされることもないAPIがプラットフォームに残り続けることは、メンテナンスコストの増大とセキュリティリスクの温存につながります。
Applet APIの削除により、JDKのインストールサイズとソースコードのフットプリントが縮小されます。また、使用されていないコードパスに潜在的なセキュリティ上の問題が残るリスクも解消されます。レガシーシステムでApplet関連のクラスをインポートしているコードは、Java 26以降コンパイルエラーが発生するため、事前に該当箇所を特定して削除または代替実装への移行を行う必要があります。JDK 17の時点で非推奨が宣言されてから約5年の猶予期間が設けられていたため、準備期間は十分に確保されていたといえます。
AOTキャッシュとG1 GC同期削減で実現するスループット5〜15%向上の仕組み
Java 26のパフォーマンス改善の中核を成すのが、AOTキャッシュのGC非依存化(JEP 516)とG1 GCの同期削減(JEP 522)です。これらはそれぞれ異なるレイヤーからアプリケーションの実行性能を底上げする改善であり、両方を組み合わせることで起動時間の短縮とスループットの向上を同時に達成できます。ここではその技術的な仕組みと、運用環境で最大限の効果を引き出すためのポイントを詳しく解説します。
Java 24のJEP 483からJava 26のJEP 516へ至るAOTキャッシュ3段階の進化
AOTキャッシュの進化はProject Leydenのロードマップに沿って3つのリリースにわたり段階的に実装されてきました。最初のステップはJava 24のJEP 483で、アプリケーションの前回実行時の情報をキャッシュに保存し、後続の実行で再利用することで起動時間とウォームアップ時間を短縮する仕組みが導入されました。この段階ではクラスのロードとリンキングに関する情報が対象でした。
第2段階のJava 25では2つのJEPがAOT関連の強化を担いました。JEP 514はAOTキャッシュ生成のコマンドライン操作を簡素化するもので、従来2ステップ必要だったトレーニング実行とキャッシュ作成を-XX:AOTCacheOutputオプションにより1コマンドで実行できるようにしました。JEP 515はAOTキャッシュにメソッドプロファイリング情報を追加するもので、JITコンパイラが最適化判断に利用するプロファイル情報を事前に保存しておくことで、ウォームアップにかかる時間をさらに短縮します。そして第3段階となるJava 26のJEP 516では、キャッシュされたオブジェクトをGC非依存のフォーマットで保存する改良が加えられました。これによりG1、ZGC、Parallel GCなどすべてのGCでAOTキャッシュが利用可能になり、GCの選択がキャッシュの互換性に影響しなくなりました。
GC非依存フォーマットで保存されるキャッシュ構造とGC切り替え時の互換性
Java 26以前のAOTキャッシュはGC固有のフォーマットで保存されていたため、キャッシュ生成時と実行時で同じGCを使用する必要がありました。たとえばG1 GCでキャッシュを生成した場合、ZGCで起動するとキャッシュが無効化され、AOTの恩恵が失われていました。JEP 516ではキャッシュ内のオブジェクトをGC実装の詳細から分離されたフォーマットで保存し、起動時にシーケンシャルにメモリへロードする方式を採用しています。
この変更により、開発環境ではG1 GCでキャッシュを生成し、本番環境ではZGCで実行するといった柔軟な運用が可能になります。コンテナ環境ではビルド時とデプロイ時でJVMフラグが異なることも珍しくないため、GC切り替え時にキャッシュの再生成が不要になるメリットは運用負荷の軽減に直結します。なお、AOTキャッシュの利用によって起動時間に悪影響が出ないことがJEPの目標として明記されており、キャッシュ読み込みのオーバーヘッドは最小限に抑えられています。
G1 GCのカードテーブル同期がボトルネックになる参照多発ワークロードの実例
G1 GCにおけるカードテーブルの同期オーバーヘッドは、すべてのワークロードで均等に発生するわけではありません。特に影響が大きいのは、オブジェクト参照の書き換えが頻繁に発生するワークロードです。たとえば大規模なグラフ構造を扱うアプリケーション、キャッシュの更新が高頻度で行われるシステム、あるいは大量のオブジェクト間リレーションを持つORMベースのデータ処理などが該当します。
従来のG1 GCではオブジェクト参照が更新されるたびに書き込みバリアが発動し、カードテーブルの該当エントリをマークします。このマーク操作においてアプリケーションスレッドとGCスレッドが同一のデータ構造にアクセスするため、メモリバリアやCAS(Compare-And-Swap)操作による同期が必要でした。JEP 522のデュアルカードテーブル方式では、アプリケーションスレッドが書き込む領域とGCスレッドが参照する領域を分離することで、この同期コストを排除しています。参照書き換えが多いワークロードほど改善幅が大きく、ベンチマークでは5〜15%のスループット向上が報告されています。
InitialRAMPercentageデフォルト値変更が大容量メモリ環境の起動に与える影響
Java 26ではJEP以外にもJVMフラグの調整が行われており、特に注目すべきなのがInitialRAMPercentageのデフォルト値変更です。このフラグはJVMが使用する初期ヒープサイズをシステムメモリに対するパーセンテージで指定するもので、従来のデフォルト値は1.5625%(1/64)でした。この値は2007年に設定されたもので、当時のシステムメモリ容量を前提とした合理的な値でしたが、現在の大容量メモリ環境では過剰なヒープサイズにつながるケースがありました。
Java 26ではこのデフォルト値が0に変更され、JVMのエルゴノミクス機能が自動的に適切な初期ヒープサイズを決定するようになります。たとえば256GBのメモリを搭載したサーバーでは、従来は約4GBの初期ヒープが確保されていましたが、実際のアプリケーションには過剰なケースもありました。この変更により起動時のメモリ消費が最適化され、コンテナ環境でのリソース効率も改善されます。ただし、明示的に-Xmsや-XX:InitialRAMPercentageを指定している場合はその設定が優先されるため、既存の設定が上書きされる心配はありません。
AOTキャッシュ+G1改善を同時適用した場合のベンチマーク計測手順と注意点
AOTキャッシュ(JEP 516)とG1 GC改善(JEP 522)はそれぞれ独立した最適化ですが、同時に適用することで起動時間とスループットの両面で改善を得られます。効果を正確に計測するには、ベースライン(JDK 25)との比較を同一ハードウェア・同一ワークロードで行うことが重要です。まずAOTキャッシュを生成するトレーニング実行を行い、その後キャッシュを利用した実行の起動時間とウォームアップ完了までの時間を計測します。
G1 GCのスループット改善は定常状態のパフォーマンスに影響するため、起動直後だけでなく一定時間の負荷テストを実施して計測する必要があります。計測時にはGCログを有効化し、停止時間やGCサイクルの頻度を確認することで改善の内訳を分析できます。注意点として、プレビュー機能を有効にした状態で計測すると結果にノイズが入る可能性があるため、正式機能のみを対象とした計測と分けて実施することが推奨されます。また、コンテナ環境ではcgroup制限によるメモリ上限がJVMエルゴノミクスに影響するため、InitialRAMPercentageの変更と合わせて検証することが望ましいです。
Lazy ConstantsやStructured Concurrencyなどプレビュー機能4本の変更点と将来展望
Java 26にはプレビュー段階の機能が4本含まれています。Lazy Constants(JEP 526)、Structured Concurrency(JEP 525)、プリミティブ型パターンマッチング(JEP 530)、PEMエンコーディング(JEP 524)です。これらはいずれも前バージョンからの継続プレビューであり、APIの洗練やフィードバックの反映が進められています。加えてインキュベーター段階のVector API(JEP 529)も11回目の搭載です。ここでは各機能の変更点と正式化に向けた見通しを整理します。
JEP 526でStableValueからLazyConstantへ名称変更されたAPIの設計意図
JEP 526はJDK 25でStable Valuesとして初めてプレビューされた機能の2回目のプレビューです。最大の変更点はAPI名の変更で、StableValueからLazyConstantにリネームされました。StableValueという名称はJVM内部の実装機構(@Stableアノテーション)に近い低レベルな表現でしたが、LazyConstantは「遅延初期化される定数」という使用者視点の概念をより直接的に表現しています。
APIの設計方針も大幅に見直されました。JDK 25ではorElseSet、setOrThrow、trySetといった低レベルメソッドが公開されていましたが、JEP 526ではこれらが削除され、値を計算する関数を受け取るファクトリメソッドのみが残されています。さらに、遅延リストや遅延マップのファクトリメソッドがjava.util.Listとjava.util.Mapインターフェースに移動され、List.ofLazy()やMap.ofLazy()として利用できるようになりました。この変更によりAPIの発見可能性が向上し、既存のコレクションAPIとの一貫性も高まっています。nullの計算値が禁止された点も、パフォーマンス最適化と不変コレクションとの整合性を確保するための重要な決定です。
LazyConstant活用でアプリ起動時のオブジェクト初期化を遅延させる実装例
LazyConstantの最も典型的なユースケースは、アプリケーション起動時に即座には必要でないオブジェクトの初期化を遅延させることです。たとえばロガーや設定オブジェクト、データベース接続プールなど、初期化コストが高いが実際に使用されるタイミングが遅いリソースが対象になります。従来のfinalフィールドではクラスのロード時またはコンストラクタでの即時初期化が必須でしたが、LazyConstantを使えば初回アクセス時まで初期化を遅延できます。
具体的な実装ではprivate final LazyConstant<Logger> logger = LazyConstant.of(() -> Logger.create(MyClass.class));のように記述し、logger.get()で初回アクセス時にサプライヤーが実行されます。初期化はスレッドセーフに最大1回だけ実行され、以降は定数としてJVMの定数折りたたみ最適化の対象になります。これにより起動パスが軽量化され、特に多数のクラスを持つ大規模アプリケーションでは起動時間の短縮効果が期待できます。ただしLazyConstantはSerializableをサポートしていないため、シリアライズが必要な場面では従来のfinalフィールドを引き続き使用する必要があります。
JEP 525のonTimeoutコールバック追加でStructured Concurrencyが得た柔軟性
JEP 525はStructured Concurrency APIの6回目のプレビューです。Structured Concurrencyは複数のスレッドで実行される関連タスクを単一の作業単位として扱うことで、エラー処理やキャンセルの信頼性を高めるプログラミングモデルです。今回のプレビューではAPIの安定性が保たれつつ、いくつかの実用的な改善が加えられています。
最も注目すべき変更はJoinerインターフェースへのonTimeout()コールバックの追加です。以前のバージョンでは、タイムアウトが発生するとscope.join()が即座にTimeoutExceptionをスローしていました。新しいonTimeout()コールバックにより、カスタムJoinerがタイムアウト時に部分的な結果やフォールバック値を返すことが可能になりました。また、Joiner.allSuccessfulOrThrow()の戻り値がSubtaskハンドルのストリームからList<T>に変更され、一般的なユースケースでのボイラープレートが削減されています。anySuccessfulResultOrThrow()はanySuccessfulOrThrow()に簡潔化され、StructuredTaskScope.open()のオーバーロードがUnaryOperator<Configuration>を受け取る形に変更されるなど、API全体の一貫性が向上しています。
JEP 530のプリミティブ型パターンマッチングが4回目プレビューで変わった支配性チェック
JEP 530はプリミティブ型をパターンマッチングの全コンテキスト(instanceofおよびswitch式・文)で使用可能にする機能の4回目のプレビューです。JDK 23で初めてプレビューされて以来、安全でないキャストや手動の範囲チェックを排除し、コードの安全性と可読性を向上させることを目的として改善が重ねられてきました。
Java 26での主な変更は「支配性チェック(dominance checks)」の強化です。switch構文において、あるパターンが別のパターンにマッチするすべての値にマッチする場合、前者が後者を「支配する」と定義されます。従来この支配性の定義は参照型のみに適用されていましたが、JEP 530ではプリミティブ型にまで拡張されました。たとえば型パターンlong qが型パターンint iを支配するようになり、コンパイラがより広範なコーディングエラーを検出できるようになっています。この機能はプレビュー段階であるため、利用にはコンパイル時と実行時に--enable-previewフラグが必要です。
Vector APIが11回目インキュベーションに留まるProject Valhalla依存の背景
JEP 529はVector APIの11回目のインキュベーションであり、JDK 25からの実質的な変更はありません。Vector APIはCPUのSIMD(Single Instruction, Multiple Data)命令を活用してベクトル演算を高速に実行するためのAPIで、JDK 16から継続的にインキュベートされてきました。x64およびAArch64アーキテクチャ上で、等価なスカラー演算を大幅に上回る性能を実現することを目指しています。
Vector APIが長期間インキュベーターに留まっている理由は、Project Valhallaとの依存関係にあります。Valhallaはアイデンティティを持たない「値型(Value Types)」をJava言語に導入するプロジェクトで、値型が利用可能になるとVector APIのメモリ表現とパフォーマンスが大幅に改善される見込みです。JEPにもValhallaの機能がプレビューで利用可能になるまでインキュベーターに留めることが明記されています。Java 26でのJEP 500(finalフィールド変更への警告)やJEP 529自体の据え置きは、Valhalla導入に向けた準備段階と捉えることもできます。Valhalla関連のJEPが2026年後半以降に動き出す可能性は高く、その際にVector APIも正式化へ向けて大きく前進することが期待されます。
finalフィールド変更警告とApplet API廃止が既存コードに与える影響と対処手順
Java 26で正式導入されたJEP 500(finalフィールド変更への警告)とJEP 504(Applet API削除)は、いずれも既存のコードベースに直接影響を及ぼす可能性がある変更です。特にJEP 500はライブラリやフレームワークがリフレクションを通じてfinalフィールドを変更しているケースを可視化するものであり、将来のリリースで変更が完全にブロックされる前に対処を進めておく必要があります。ここでは具体的な対処手順と、CIパイプラインを活用した早期検出の方法を解説します。
JEP 500のallow・warn・debug・denyの4モード切り替えで段階的に移行する方法
JEP 500が提供する--illegal-final-field-mutationオプションは、段階的な移行を支援する4つのモードを備えています。allowモードは警告を出さずに変更を許可するもので、移行初期に既存の動作を維持したい場合に使用できます。デフォルトのwarnモードでは、ディープリフレクションによるfinalフィールドの変更が初めて検出された時点でJVMログに警告メッセージが出力されます。この警告にはフィールド名、対象クラス、変更を行ったクラスとモジュールの情報が含まれるため、影響箇所の特定に役立ちます。
debugモードはwarnに加えてスタックトレースも出力し、すべての変更箇所を詳細に追跡できます。開発環境やステージング環境でこのモードを有効にすることで、影響範囲の全体像を把握するのに有効です。denyモードでは変更そのものがブロックされ、IllegalAccessExceptionが発生します。将来のJavaリリースではdenyがデフォルトになる予定のため、Java 26の段階でdenyモードをテスト環境で試行しておくことが推奨されます。段階的にallow→warn→debug→denyと移行することで、影響を制御しながらコードベースのクリーンアップを進められます。
Hibernateやテストフレームワークがfinal変更警告を出しやすい3つの典型パターン
finalフィールドの変更警告が発生しやすいのは、ディープリフレクションを多用するフレームワークやライブラリです。第1の典型パターンはORMフレームワークによるエンティティのフィールド操作です。Hibernateはプロキシ生成やレイジーローディングの過程でリフレクションを使用しており、finalフィールドを持つエンティティクラスで警告が発生する可能性があります。Hibernate 7.xではJava 26対応が進められていますが、古いバージョンを使用している場合は注意が必要です。
第2のパターンはテストフレームワークによるモック生成です。MockitoやPowerMockなどのモックライブラリは、テスト対象クラスのfinalフィールドをリフレクションで置き換えることがあります。特にレガシーコードのテストでfinalフィールドのモック化が行われている場合、Java 26で警告が表示されます。第3のパターンはシリアライゼーション・デシリアライゼーションライブラリです。Jacksonなどのライブラリがfinalフィールドを持つオブジェクトをデシリアライズする際に、リフレクションを通じてフィールドに値を設定するケースが該当します。これらの警告が自分のコードから発生しているか、依存ライブラリから発生しているかを区別し、対応の優先順位を判断することが重要です。
–enable-final-field-mutationオプションでモジュール単位に許可する設定例
すべてのfinalフィールド変更警告を一度に解消できない場合、--enable-final-field-mutationオプションを使ってモジュール単位で変更を許可する方法があります。このオプションはカンマ区切りでモジュール名を指定でき、指定されたモジュール内でのfinalフィールド変更に対しては警告が出力されなくなります。
たとえば名前なしモジュール(クラスパス上のライブラリ)からの変更を許可する場合は--enable-final-field-mutation=ALL-UNNAMEDと指定します。特定のモジュールのみ許可する場合は--enable-final-field-mutation=org.hibernate.orm.core,com.fasterxml.jackson.databindのように記述します。この設定はあくまで一時的な回避策であり、ライブラリ側がJava 26互換のバージョンをリリースした時点で順次設定を削除していくことが望ましい運用です。CIの設定ファイルに明示的にコメントを残し、どのモジュールをなぜ許可しているかを記録しておくことで、将来の削除漏れを防げます。
Applet API削除後にjavacコンパイルエラーが発生するレガシーコードの修正手順
JEP 504によるApplet API完全削除で影響を受けるのは、java.appletパッケージのクラスをインポートまたは参照しているコードです。具体的にはjava.applet.Applet、java.applet.AppletContext、java.applet.AppletStub、java.applet.AudioClipなどが対象になります。Java 26でこれらのクラスを参照しているコードをコンパイルすると、クラスが見つからないエラーが発生します。
- プロジェクト全体で
java.appletパッケージへの参照を検索する - 該当箇所がテストコードや未使用のレガシーモジュールであれば削除する
- 代替実装が必要な場合はJavaFXやSwingベースのスタンドアロンアプリケーションへ移行する
- サードパーティライブラリが内部でApplet APIを参照している場合はライブラリの更新版を確認する
- コンパイルが通ることを確認し、テストスイートを実行して動作を検証する
JDK 17で非推奨が宣言されてからJDK 26での完全削除まで約5年が経過しているため、多くのアクティブなプロジェクトではすでにApplet API依存が解消されていることが想定されます。ただしレガシーシステムや社内フレームワークでは見落としが残っている可能性があるため、Java 26への移行前に一度スキャンを実施しておくと安全です。
CIパイプラインにJava 26を追加して警告を早期検出するGitHub Actions設定例
JEP 500の警告を早期に検出するためには、CIパイプラインにJava 26を組み込むのが効果的です。本番環境ではJDK 25 LTSを使い続けつつ、CIマトリクスにJDK 26を追加してビルドとテストを実行し、ログ内の警告を検出する体制を構築します。GitHub Actionsではactions/setup-javaアクションを使ってJDK 26をセットアップできます。
実行後のログから警告を抽出するには、grep "has been mutated" build.logのようなコマンドで対象行をフィルタリングします。さらに踏み込んだ検証として、--illegal-final-field-mutation=denyを指定した実行をCI上で行い、将来のJavaリリースでデフォルト化された際の影響を事前に確認するアプローチもあります。このdenyモードのジョブは当初は失敗が許容される情報収集用として設定し、対応が完了したモジュールから段階的に必須化していくことで、計画的な移行が実現できます。Spring Framework 7.0はすでにリフレクション使用のクリーンアップが完了しているため、フレームワーク本体からの警告は少ないと見られます。
非LTS版Java 26をJDK 25 LTSと併用する際の判断基準と運用上の注意点
Java 26は非LTSリリースであり、6か月のPremier Supportが終了するとセキュリティアップデートも停止します。一方で、GCの改善やHTTP/3対応など即座に恩恵を受けられる機能も含まれています。非LTS版を採用するかどうかは、プロジェクトの性質やリスク許容度によって判断が分かれるところです。ここではJDK 25 LTSとの使い分けの基準や、次期リリースを見据えた計画の立て方を解説します。
6か月サポートの非LTSを本番投入すべきケースと避けるべきケースの判断基準
非LTS版であるJava 26を本番環境に投入するのが合理的なケースはいくつかに限られます。第1に、短期間のプロジェクトやPoC(概念実証)であり、6か月以内にプロジェクトが完了するか次のバージョンに移行する体制が整っている場合です。第2に、HTTP/3対応やG1 GC改善など特定のJEPによるパフォーマンス向上がビジネス要件上不可欠であり、JDK 25 LTSでは得られない改善を必要としている場合です。
一方で避けるべきケースも明確です。長期稼働が前提のエンタープライズシステムでは、6か月後にサポートが切れるリスクは許容しにくいでしょう。また、依存ライブラリがJava 26の動作検証を完了していない場合、予期しない互換性問題が発生するリスクがあります。社内の運用チームがJDKのバージョンアップを迅速に実施できない体制であれば、LTS版に留まるのが安全です。判断の基本原則は、アップグレードとダウングレードの両方を迅速に実行できる体制があるかどうかです。コンテナ化されたマイクロサービスであれば切り替えは比較的容易ですが、モノリシックなアプリケーションでは慎重な判断が求められます。
Oracle・Eclipse Temurin・Red Hatなど主要ディストリビューション別サポート期間比較
Javaのサポート期間はディストリビューションによって異なるため、採用するJDKの選定時にはサポートポリシーを確認しておく必要があります。Oracle JDKはLTS版に対して長期のPremier Supportを提供しますが、非LTS版のサポートは6か月間に限定されます。JDK 25 LTSのOracle無償サポートは2033年9月まで、商用サポートは2038年9月までが目安です。
| ディストリビューション | JDK 25 LTSサポート期間 | JDK 26(非LTS)サポート | 特記事項 |
|---|---|---|---|
| Oracle JDK | 無償:2033年9月まで | 6か月(Premier) | 商用は2038年9月まで |
| Eclipse Temurin(Adoptium) | 通常4〜8年 | 次バージョンリリースまで | コミュニティ主導の無償ビルド |
| Red Hat OpenJDK | RHELライフサイクルに準拠 | 原則非対応 | LTS版のみ長期サポート |
| Amazon Corretto | 通常8年以上 | 次バージョンリリースまで | AWS環境との統合が強み |
非LTS版であるJDK 26は、ほとんどのディストリビューションで短期間のサポートしか提供されません。本番環境での採用を検討する場合は、利用中のディストリビューションのサポートポリシーを事前に確認し、セキュリティパッチの提供期間を把握しておくことが不可欠です。
JDK 25 LTSを本番維持しつつJava 26をCI検証用に並行運用する構成例
多くのチームにとって最も実用的なのは、JDK 25 LTSを本番環境で維持しつつ、JDK 26をCI検証用に並行運用する構成です。この構成により、本番環境の安定性を損なうことなく、JEP 500のfinalフィールド変更警告やApplet API削除の影響を早期に把握できます。具体的にはCIのビルドマトリクスにJDK 25とJDK 26の両方を設定し、JDK 25でのビルド・テストを必須ジョブ、JDK 26を情報収集用の任意ジョブとして構成します。
JDK 26のジョブでは通常のビルドとテストに加え、--illegal-final-field-mutation=denyを指定した実行を別途設けることで、将来のデフォルト変更に備えた検証も同時に行えます。ジョブの結果はSlackやメールで通知する設定にしておくと、チーム全体で課題の共有がスムーズになります。この並行運用は次期リリースのJDK 27だけでなく、さらに先のLTSバージョンへの移行準備としても有効です。新しいJDKがリリースされるたびにCIマトリクスを更新し、常に1バージョン先の互換性を検証し続ける体制を確立しておくことが理想的です。
JDK 27で予定されるポスト量子暗号TLS対応を見据えたアップグレード計画の立て方
Java 26の次のリリースであるJDK 27は2026年9月にGA(一般提供)が予定されています。現時点でJDK 27にターゲットされているのはJEP 527(Post-Quantum Hybrid Key Exchange for TLS 1.3)で、ポスト量子暗号に対応したTLSハイブリッド鍵交換が導入される予定です。量子コンピュータの実用化に備えたセキュリティ強化は、金融や医療など高いセキュリティ要件を持つ業界にとって特に重要なテーマです。
アップグレード計画を立てるうえでは、JDK 26で検出されたfinalフィールド変更警告の解消をJDK 27リリースまでに完了させることを一つのマイルストーンとして設定するのが合理的です。JDK 27が非LTSであるかLTSであるかはまだ発表されていませんが、次のLTSは順当にいけばJDK 29(2027年9月)になる可能性があります。長期的なアップグレード計画では、現在のJDK 25 LTSからJDK 29 LTSへの移行を最終目標とし、途中のJDK 26〜28で発生する変更をCIで段階的に検証していくロードマップが有効です。
非LTSバージョンをスキップして次期LTSまで待つ場合に失うランタイム改善の具体値
非LTS版をすべてスキップしてLTS間で直接移行するアプローチは運用負荷が低い一方で、途中リリースのランタイム改善をリアルタイムに享受できないトレードオフがあります。Java 26をスキップした場合に失われる主な改善を具体値で整理します。
- G1 GCのデュアルカードテーブル方式による参照多発ワークロードでのスループット5〜15%向上
- AOTオブジェクトキャッシュのGC非依存化によるZGC環境での起動時間短縮
- HTTP/3プロトコルのJDK標準サポートによる外部ライブラリ不要の通信高速化
- InitialRAMPercentageデフォルト値変更によるコンテナ環境での初期メモリ最適化
これらはいずれもJDKをアップグレードするだけで追加設定なく恩恵を受けられる改善です。
JDK 25 LTSにはCompact Object Headers(オブジェクトヘッダを12〜16バイトから8バイトに縮小)が含まれており、メモリ使用量は約22%削減されていました。Java 26のG1 GC改善はこれとは異なるレイヤーの最適化であるため、両方を組み合わせた場合の総合的なパフォーマンス改善はさらに大きくなります。これらの改善はJDK 27以降に引き継がれるため最終的にはLTSでも享受できますが、パフォーマンスが競争優位に直結するサービスでは半年分の遅れがビジネス上の損失になる可能性もあります。自社サービスのワークロード特性を踏まえたうえで、スキップのコストとアップグレードの運用コストを天秤にかけて判断することが重要です。
Spring Boot・Hibernate環境でJava 26を導入する際のCI設定と依存関係チェックリスト
Javaのバージョンアップは言語仕様やJVMの変更だけでなく、フレームワークやライブラリとの互換性が大きな課題となります。特にSpring BootとHibernateはエンタープライズJava開発の中核を成すフレームワークであり、新しいJDKへの対応状況がプロジェクト全体の移行可否を左右します。ここではJava 26を導入する際の具体的な設定手順とチェック項目を整理します。
Spring Boot 4.xのJava 26サポート状況とベストエフォート対応の意味
Spring Boot 4.0.xはJava 25を公式にサポートしており、Java 26に対しては「ベストエフォート(best effort)」の対応となっています。ベストエフォートとは、実用上は動作するが公式のドキュメントや互換性保証の対象外であることを意味します。Spring Frameworkの基盤であるSpring Framework 7.0はリフレクション使用のクリーンアップがすでに完了しており、JEP 500のfinalフィールド変更警告がSpring Framework本体から発生する可能性は低いと考えられます。
ただしベストエフォートであるため、Java 26固有のエッジケースでバグが発生した場合、Springチームの対応優先度は公式サポート版よりも低くなる可能性があります。実務上は、Spring Boot 4.0.xの次のパッチリリースでJava 26の公式ドキュメントが追加されると見込まれています。Java 26を導入する場合は、Spring Bootの最新パッチバージョンを使用し、リリースノートでJDK互換性に関する記述を確認することが推奨されます。開発チームのリスク許容度に応じて、ステージング環境での検証を経てから本番適用するかどうかを判断してください。
Hibernate 7.xとJacksonでfinalフィールド反射警告が出る場合の対応優先順位
JEP 500のfinalフィールド変更警告がフレームワーク側から発生した場合、自分のコードではなく依存ライブラリが原因であるため、直接修正できないケースが多くなります。対応の優先順位を適切に設定することが重要です。まず最優先で確認すべきは、該当ライブラリのJava 26対応バージョンがすでにリリースされているかどうかです。
Hibernate 7.xはJava 26対応を進めていますが、バージョンによっては対応が完了していない場合があります。プロジェクトで使用中のHibernateバージョンのリリースノートやイシュートラッカーを確認し、Java 26対応パッチがあれば適用します。Jacksonについても同様で、jackson-databindがfinalフィールドへのリフレクションアクセスを行うパスが存在する場合があります。対応版が未リリースの場合は、--enable-final-field-mutation=ALL-UNNAMEDで一時的に警告を抑制しつつ、ライブラリの更新を待つのが実用的な判断です。自分のコードから発生する警告は即座に修正し、ライブラリ由来の警告は一時許可で対処するという二段構えのアプローチが効率的です。
Maven・GradleのビルドファイルでJava 26ターゲットを設定する具体的な記述例
Java 26をビルドターゲットとして設定するには、MavenまたはGradleのビルドファイルを更新する必要があります。Mavenの場合はpom.xmlでソースとターゲットのJavaバージョンを指定します。<maven.compiler.source>26</maven.compiler.source>と<maven.compiler.target>26</maven.compiler.target>を設定するか、<maven.compiler.release>26</maven.compiler.release>を使用します。プレビュー機能を利用する場合はmaven-compiler-pluginの設定に<compilerArgs><arg>--enable-preview</arg></compilerArgs>を追加します。
Gradleの場合はbuild.gradleでjava { toolchain { languageVersion = JavaLanguageVersion.of(26) } }と設定するのが推奨されるアプローチです。Gradle Toolchainを使用すると、ビルド環境にインストールされたJDKを自動検出して利用するため、チームメンバー間でのJDKバージョンの不一致を防げます。プレビュー機能を使う場合はtasks.withType(JavaCompile) { options.compilerArgs += ['--enable-preview'] }を追加します。いずれのビルドツールでも、CI上のJDKバージョンとビルドファイルの設定が一致していることを確認してください。
RestClientでHTTP/3を有効化する際のSpring設定とQUICフォールバック検証手順
JEP 517によるHTTP/3対応をSpring Boot環境で活用するには、JDK標準のHttpClientをバックエンドとして使用するRestClientの設定を変更します。Spring Boot 4.xのRestClientはデフォルトでJDK HttpClientを利用できるため、HttpClientの生成時にHTTP/3バージョンを指定することでSpring経由の通信でもHTTP/3が使用可能になります。
設定はHttpClientのビルダーでHttpClient.Version.HTTP_3を指定し、そのクライアントをRestClientのファクトリに渡す形になります。サーバー側がHTTP/3に対応していない場合は自動的にHTTP/2にフォールバックするため、クライアント側でプロトコルネゴシエーションの失敗を心配する必要はありません。ただし、検証時にはHTTP/3で実際に通信が行われているかをログやネットワークキャプチャで確認しておくことが重要です。QUICプロトコルはUDP上で動作するため、ファイアウォールやロードバランサーでUDPポートがブロックされている環境ではHTTP/3接続が成立しない可能性があります。検証手順としては、まずHTTP/3対応の外部サーバーへの接続テストを行い、次に自社環境のネットワーク構成での疎通確認を実施するのが確実です。
OpenRewriteを使ったJava 25→26の自動リファクタリングで削減できる手作業工数
OpenRewriteはJavaコードの自動リファクタリングツールであり、JDKバージョン間の移行を支援するレシピ(変換ルール)を提供しています。Java 25への移行レシピであるorg.openrewrite.java.migrate.UpgradeToJava25はすでに公開されており、非推奨APIの置き換えやビルドファイルの更新を自動的に適用できます。Java 26向けのレシピも今後追加されることが見込まれます。
OpenRewriteはMavenとGradleの両方で利用可能で、Mavenではrewrite-maven-pluginを追加してレシピを指定するだけで実行できます。自動適用されるのは非推奨APIの置き換え、ビルドファイルのバージョン番号更新、プラグインの互換バージョンへのアップグレードなどです。手作業でこれらを実施すると、プロジェクト規模によっては数時間から数日を要しますが、OpenRewriteを使えば数分で完了します。ただし自動変換の結果は必ずレビューが必要であり、特にビジネスロジックに影響する変更がないかの確認は省略できません。OpenRewriteの適用後にテストスイートを実行し、変換による回帰がないことを検証するフローをCIに組み込んでおくと安全です。