Java 8で止まった業務システムを上げるなら、移行先はJava 25です。2026年9月15日にJava 27が出ましたが非LTSで、Temurinの提供期限は2027年3月、CorrettoのEOLは2027年4月です。次のLTSであるJava 29は、Oracleの計画では2027年9月です。待つ理由はありません。この記事では、Java 8でコンパイルした同じJARをJava 8・25・26・27で実際に動かし、どこで落ち、どこで黙って結果が変わるかを確かめたうえで、壊さずに上げる手順と移行先の判断基準を示します。
まとめ
Java 8からの近代化は、ランタイムを先に上げ、ライブラリとフレームワークを直し、最後にコンパイルターゲットを上げる順で進めます。実測では、Java 8のJARはJava 25・26・27のどれでも起動しました。落ちたのは、Java 11で削除されたJAXB、Java 17で強化されたカプセル化を破るリフレクション、システムクラスローダーのキャスト、Security Manager、Java 8時代のGCログオプションの5つです。どれも移行先をJava 25にしても27にしても同じように落ちるので、バージョン選びでは避けられません。
落ちないのに結果が変わる箇所は、日本の現場では文字コードと日付書式です。Shift_JISのロケールで動かすと、Java 8の既定文字コードはShift_JIS、Java 25はUTF-8でした。JDK 26・27の仕様と実測で確かめると、次の2点は思い込みやすい誤りです。sun.misc.Unsafe はJDK 26・27でも既定は警告止まりで、例外にはなりません。java.locale.providers=COMPAT はJDK 23で削除され、指定すると日本語の書式が英語に変わります。
移行先はJava 25を既定にし、Spring Boot 2.7から抜けられない場合など依存側の上限があるときだけJava 21で止めます。最初の作業は、手元のJARに jdeps と jdeprscan を当てて、壁の数を数えることです。
Javaのバージョンとサポート期限の現在地(2026年10月)
現行LTSはJava 25、最新はJava 27、次のLTSはJava 29
Eclipse Adoptiumのリリース情報API(api.adoptium.net/v3/info/available_releases)を2026年10月19日に引くと、最新のLTSは25、最新の機能リリースは27でした。無償ビルドの提供期限はAdoptiumのサポートロードマップ、Amazon Correttoの終了日はCorretto FAQが公表しています。
| 版 | 位置づけ | Temurin最新ビルド | Temurin提供期限 | Corretto終了 |
|---|---|---|---|---|
| Java 8 | LTS | 8u504-b01 | 少なくとも2030年12月 | 2030年12月 |
| Java 11 | LTS | 11.0.32.1+1 | 少なくとも2027年10月 | 2032年1月 |
| Java 17 | LTS | 17.0.20.1+1 | 少なくとも2027年10月 | 2029年10月 |
| Java 21 | LTS | 21.0.12.1+1 | 少なくとも2029年12月 | 2030年10月 |
| Java 25 | LTS(現行) | 25.0.4.1+1 | 少なくとも2031年9月 | 2032年10月 |
| Java 27 | 非LTS(2026-09-15 GA) | 27+35 | 2027年3月 | 2027年4月 |
Java 25の次のLTSについて、OracleはJava SE FAQで「Java 29 in September 2027」と予定を示しています。Java 27で何が変わったかはJava 27の非LTS運用と既定化された機能で扱っているので、ここでは移行先にしない理由だけを後の章で述べます。
Oracle・Red Hatのサポート期限とライセンス変更予定
有償サポートの締め切りは配布元ごとに違います。OracleのJava SE Support Roadmapの表は次のとおりです。
| 版 | Premier Support終了 | Extended Support終了 |
|---|---|---|
| Java 8 | 2022年3月 | 2030年12月 |
| Java 11 | 2023年9月 | 2032年1月 |
| Java 17 | 2026年9月以降 | 2029年9月以降 |
| Java 21 | 2028年9月以降 | 2031年9月以降 |
| Java 25 | 2030年9月以降 | 2033年9月以降 |
Java 17のPremier Supportは2026年9月で区切りを迎えましたが、同じページの脚注は「The Extended Support fee will be waived for the period October 2026 – September 2029 for Java SE 17.」と、2029年9月までExtended Supportの追加料金を取らないと明記しています。同じロードマップによれば、Oracle JDK 21の更新は2026年10月のCritical Patch Update(予定日は2026年10月20日)からOTNライセンスでの提供に切り替わります。NFTC(無償で商用利用できる条件)を前提にOracle JDK 21を本番で使っていた組織は、この時点で配布元か契約を見直すことになります。無償の範囲と価格の考え方はOpenJDKの商用利用とOracle JDKとの違いにまとめています。
RHEL上のOpenJDKを使っている場合はRed HatのOpenJDKライフサイクルが基準です。OpenJDK 8のフルサポートは2026年11月30日に終わり、以後は延長サポート(ELS-1、2032年12月31日まで)になります。Java 8の期限として最も近いのはこの日付です。
Java 8に留まると上げられなくなるフレームワーク
Java 8のまま動いていても、周辺のライブラリが新しい版を出すたびに取り残されます。上限を決めるのはJDKではなくフレームワークです。Spring Bootの公式のSystem Requirementsで、各版が対応するJavaの範囲は次のとおりです。
| Spring Boot | 最低Java | 互換の上限 |
|---|---|---|
| 2.7.18 | Java 8 | Java 21 |
| 3.5.16 | Java 17 | Java 25 |
| 4.0.8 | Java 17 | Java 26 |
| 4.1.1 | Java 17 | Java 26 |
Java 8で動く最後の系列である2.7.18は、公式ドキュメントで互換の上限をJava 21としています。Spring Boot 2.7のままJDKだけをJava 25へ上げると、公式の保証範囲から外れます。Java 25を移行先にするなら、3.5系以上への移行が前提になります。脆弱性の修正版がJava 17以上を要求したとき、Java 8のシステムはパッチより先にJDK移行から始めなければなりません。障害対応の最中にJDKを上げる事態は、計画的な移行より高くつきます。
Javaそのものの位置づけは揺らいでいません。TIOBE Indexの2026年10月版でJavaは4位、レーティングは8.41%です。
同じJava 8のJARを8・25・26・27で動かした結果
変更点の一覧を読むより、手元で同じJARを動かすほうが早く確実です。Temurin 8u504-b01の javac で6つの検査クラスをコンパイルし(クラスファイルのバージョンは52.0)、1つのJARにまとめて、Temurin 25.0.4.1・Temurin 26.0.2.1・Zulu 27(27+35)でそのまま実行しました。環境はmacOS(x86_64、16論理CPU)です。
| 検査 | Java 8 | Java 25 | Java 26 | Java 27 |
|---|---|---|---|---|
| JAXBの利用 | 動く | NoClassDefFoundError | 同左 | 同左 |
| URLClassLoaderへのキャスト | 動く | ClassCastException | 同左 | 同左 |
| String.valueのsetAccessible | 動く | InaccessibleObjectException | 同左 | 同左 |
| setSecurityManager | 動く | UnsupportedOperationException | 同左 | 同左 |
| -XX:+PrintGCDateStamps | 起動する | 起動しない | 同左 | 同左 |
| Unsafe.allocateMemory | 動く | 警告4行のあと動く | 同左 | 同左 |
| 既定GC(16CPU) | Parallel | G1 | G1 | G1 |
| 既定GC(1CPU指定) | Serial | Serial | Serial | G1 |
| 日付FULL書式(ja) | 2026年10月19日 | 2026年10月19日月曜日 | 同左 | 同左 |
Java 25・26・27で結果が分かれたのは、1CPUの環境で選ばれるGCだけでした。落ちる箇所はバージョンを選んでも減りません。実際に出た例外のうち、原因の読み取りに使う3つを載せます。
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/JAXBContext
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBContext
java.lang.reflect.InaccessibleObjectException: Unable to make field private final byte[]
java.lang.String.value accessible: module java.base does not "opens java.lang" to unnamed module
Unrecognized VM option 'PrintGCDateStamps'
Error: Could not create the Java Virtual Machine.
1つ目と2つ目はアプリケーションが動き出してから、該当するコードを通った時点で落ちます。テストがその経路を通らなければ本番まで気づきません。3つ目はJVMが起動しないので、起動スクリプトを直すまで何も動きません。
起動・実行を妨げる非互換とUnsafeの警告
JEP 320で削除されたJava EE・CORBAモジュール(Java 11)
Java 11で、JEP 320によりJAXB・JAX-WS・JAF・Common Annotations・CORBA・JTAのモジュールがJDKから削除されました。Java 8ではJDKに同梱されていたため、依存を宣言せずに javax.xml.bind.JAXBContext を使っているコードが珍しくありません。代わりの依存はMicrosoft Learnの移行ガイドが対応表を出しています。
| 削除されたモジュール | 技術 | 代わりの依存 |
|---|---|---|
| java.xml.bind | JAXB | org.glassfish.jaxb:jaxb-runtime(javax用は2.3系) |
| java.xml.ws | JAX-WS | com.sun.xml.ws:jaxws-rt |
| java.activation | JAF | javax.activation:activation |
| java.xml.ws.annotation | Common Annotations | javax.annotation:javax.annotation-api |
| java.corba | CORBA | org.glassfish.corba:glassfish-corba-orb |
| java.transaction | JTA | javax.transaction:jta |
見落としやすいのは静的解析での見え方です。Java 25の jdeprscan はJAXBを「削除されたAPI」とは報告せず、「クラスjavax/xml/bind/JAXBContextが見つかりません」というエラー行を出しました。jdeps -s でも依存先が「見つかりません」と表示されるだけです。棚卸しの出力でこの行を雑音として読み飛ばすと、JAXBの依存を取りこぼします。
強いカプセル化とシステムクラスローダーの変更(Java 9〜17)
Java 9のモジュールシステム導入で、JDK内部のクラスへのリフレクションは段階的に締められ、Java 17のJEP 403で既定の抜け道がなくなりました。実測では、String.value への setAccessible(true) がJava 25で InaccessibleObjectException になりました。起動オプションに --add-opens java.base/java.lang=ALL-UNNAMED を付けると同じコードが通ります。これは移行期間の延命措置で、外せる状態にするまでが移行作業です。どの操作が禁止されたかはJavaリフレクションでJava 17以降に禁止される操作で詳しく扱っています。
同じJava 9で、システムクラスローダーは URLClassLoader ではなくなりました。実行時にJARをクラスパスへ差し込むため (URLClassLoader) ClassLoader.getSystemClassLoader() と書いていた処理は、ClassCastException で落ちます。プラグイン機構を自作している業務アプリケーションで見つかることが多い箇所です。
JDK 24で恒久無効化されたSecurity Manager
JDK 24以降、Security Managerは有効にできません(JEP 486)。実測では、Java 25・26・27とも -Djava.security.manager=allow を付けると「A command line option has attempted to allow or enable the Security Manager. Enabling a Security Manager is not supported.」でJVMの初期化が失敗し、実行時に System.setSecurityManager() を呼ぶと「Setting a Security Manager is not supported」の UnsupportedOperationException になりました。-Djava.security.manager=disallow は起動を妨げません。
自社コードで使っている例は少なくても、古いアプリケーションサーバーやプラグイン基盤が起動スクリプトでこのオプションを付けていることがあります。JVMの中でサンドボックスを組む設計は成立しなくなったので、隔離はコンテナやOSの仕組みに移します。
削除されたJVMオプション(GCログ)
Java 9でGCログの指定は -Xlog に統一されました(JEP 271)。Java 8の起動スクリプトをそのまま使うと、オプションによって扱いが分かれます。実測では、-XX:+PrintGCDetails と -Xloggc は非推奨の警告を出して -Xlog に読み替えられ、-XX:+PrintGCDateStamps は「Unrecognized VM option」でJVMが起動しませんでした。起動スクリプトの -XX オプションは、移行前に新しいJDKの java で1本ずつ起動を確かめてください。
sun.misc.Unsafe のメモリアクセス(既定はJDK 27でも警告止まり)
JEP 471は、Unsafeのメモリアクセスメソッドを段階的に止める計画として「Phase 3, throwing exceptions by default, in JDK 26 or later」と書いています。JDK 26で例外が既定になったと読んだ解説もありましたが、実際にはJava SE 27のjavaコマンド仕様でも --sun-misc-unsafe-memory-access の既定値は warn です。手元の実行でも、Java 25・26・27とも「WARNING: A terminally deprecated method in sun.misc.Unsafe has been called」で始まる4行の警告を出したあと処理は続きました。
既定が変わるのは時間の問題です。--sun-misc-unsafe-memory-access=deny を付けると、Java 25でも UnsupportedOperationException: allocateMemory で落ちる将来の挙動を再現できます。このAPIを呼んでいるのは、たいていシリアライズやバイトコード操作の古いライブラリです。テスト環境だけ deny で回せば、該当するライブラリを今のうちに洗い出せます。jdeps --jdk-internals でも sun.misc.Unsafe への依存として検出できます。代替はオンヒープが VarHandle(JDK 9)、オフヒープがForeign Function & Memory API(JDK 22で正式機能)です。
落ちずに結果が変わる3つの挙動差
既定文字コードのUTF-8化(JEP 400・JDK 18)
日本の業務システムで最も影響が大きいのがこれです。JEP 400で、JDK 18以降の既定文字コードはOSのロケールにかかわらずUTF-8になりました。ロケールを ja_JP.SJIS にして同じJARを動かすと、Java 8は defaultCharset=Shift_JIS、Java 25は defaultCharset=UTF-8 で、OS側の文字コードは native.encoding=SJIS として別に見えるだけでした。日本語版Windowsの既定(MS932)で文字コードを指定せずに FileReader や new String(bytes) を使っていたコードは、例外を出さずに文字化けします。
JEP 400は従来の決め方に戻す指定として -Dfile.encoding=COMPAT を用意しています。ただし今回のmacOS・Temurin 25.0.4.1の検証では、この指定で file.encoding プロパティはSJISになったものの、Charset.defaultCharset() はUTF-8のままでした。戻し方として頼れる指定ではありません。直すのは、ファイル・ソケット・標準出力を読み書きする箇所すべてで文字コードを明示することです。
CLDRによる日付・時刻書式の変化とCOMPATの削除
Java 9でロケールデータの既定がCLDRに変わり(JEP 252)、書式の結果が変わりました。実測では、日本語ロケールのFULL書式がJava 8の「2026年10月19日」からJava 25の「2026年10月19日月曜日」に変わりました。米国ロケールの短い日時は「10/19/26 9:05 AM」が「10/19/26, 9:05 AM」になり、AMの前の空白は通常のスペースではなくナローノーブレークスペース(U+202F)でした。
この差はパースで事故になります。Java 25が出力した時刻をJava 8側で DateFormat でパースすると ParseException になりました。逆に、Java 25と27の java.time で「9:05 AM」(通常のスペース)をローカライズ書式のままパースすると「could not be parsed at index 4」で失敗し、parseLenient() を付けると通りました。新旧のJDKが混在する期間に、画面表示用の書式で作った文字列を別システムが読む構成は、移行前に固定パターン(DateTimeFormatter.ofPattern)へ置き換えてください。
Java 8の書式に戻す手段として -Djava.locale.providers=COMPAT,SPI がよく紹介されますが、JDK 23のリリースノートのとおりCOMPATは削除済みです。Java 25と27で指定すると「COMPAT locale provider has been removed」の警告が出て、日本語ロケールのFULL書式が「Monday, October 19, 2026」、通貨が「JPY 1,234,567」と英語の書式で出力されました。この指定が起動スクリプトに残っていると、帳票や画面の日付が英語になります。
既定GCの変化と1CPU環境でのJava 25・27の違い
16CPUの環境では、Java 8の既定GCがParallel、Java 25以降がG1でした。CPUを1つに制限すると(-XX:ActiveProcessorCount=1)、Java 8・25・26はSerial GCを選び、Java 27だけがG1を選びました。Java 27で入ったJEP 523(全環境でG1を既定にする変更)によるものです。CPUを1つしか割り当てないコンテナでJava 25を動かすと、G1ではなくSerial GCで動いています。Java 8との性能比較はGCを -XX:+UseParallelGC などで揃えてから行い、チューニングは動作確認の後に回します。GCの種類とログの読み方はJavaのガベージコレクションの仕組みとチューニング手順を参照してください。
近代化の実行手順|壊さずに上げる5ステップ
ステップ1:jdeps と jdeprscan による棚卸し
どちらもJDKに同梱されていて、再コンパイルせずに既存のJARへ当てられます。サードパーティのライブラリも同じように評価できます。
# JDK内部API(sun.* など)への依存を洗い出す
jdeps --jdk-internals --multi-release 25 --class-path 'libs/*' app.jar
# 削除予定のAPIの使用箇所を洗い出す(--for-removal は --release 6〜8 と併用できない)
jdeprscan --release 25 --for-removal --class-path 'libs/*' app.jar
検査用のJARに当てた結果は、jdeps が UnsafeMem -> sun.misc.Unsafe JDK internal API (jdk.unsupported)、jdeprscan が SecurityManager と System::setSecurityManager を forRemoval=true として報告しました。JAXBは前述のとおり「見つかりません」のエラー行としてしか出ません。リフレクションや ServiceLoader 経由の参照はどちらのツールでも検出できないので、ステップ2の実行で補います。検出件数は棚卸しの入口です。修正の共通化が可能な箇所、依存製品の更新、回帰テストの範囲に分けて工数を見積もります。
ステップ2:再コンパイル前のランタイム更新と回帰テスト
Java 25のJVMはJava 8のクラスファイル形式を読み込めますが、削除されたAPIや依存ライブラリによって、起動または実行に失敗する場合があります。最初は javac のターゲットを変えず、実行するJDKだけを差し替えます。こうすると「JDKを上げたこと自体で壊れるもの」と「新しい文法で壊れるもの」を分けて見られます。回帰テストは次の指定で流すと、将来の既定に合わせた状態で問題を拾えます。
java --sun-misc-unsafe-memory-access=deny \
-Djava.security.manager=disallow \
'-Xlog:gc*:file=gc.log' \
-jar app.jar
ステップ3:ライブラリとフレームワークの底上げ
ステップ2で落ちたライブラリを、新しいJDKに対応した版へ上げます。移行工数の大半はここに入ります。Spring Boot 2.7から3.x以降へ上げると、2020年12月8日リリースのJakarta EE 9で決まった名前空間の変更(javax.* から jakarta.*)が一斉に発生します。Java EE由来の対象APIのimport文は機械的に置換できますが、Java SEに残るjavaxパッケージまで一括置換してはいけません。XML設定やリフレクションの文字列で書かれたクラス名も確認します。JDKの移行とJakarta EEの移行を同じリリースに入れると、どちらが原因で落ちたか切り分けられません。リリースを分けてください。Spring Boot 4への移行で変わる点はSpring Boot 4とSpring Boot 3との違いで確認できます。
ビルドツールも前提を満たす必要があります。GradleでJava 25を扱うには9.1.0以降が必要です。Mavenの maven-compiler-plugin は最低版が一律に決まっているわけではないので、使用するJDK・コンパイラ・関連プラグインの組み合わせで release 25のビルドが通るかを確かめます。CIで固定しているビルドツールが古いまま、という理由で止まる例は少なくありません。
ステップ4:OpenRewriteによる変更差分の生成と確認
OpenRewriteのUpgradeToJava25は、Java 8・11・17のプロジェクトに8→11、11→17、17→21、21→25のレシピを順に当てる複合レシピです。Java 8の pom.xml と、new Integer(42)・System.getSecurityManager()・JAXBを使う1クラスの小さなプロジェクトで、変更内容だけを出力する dryRunNoFork を実行しました。
mvn -B org.openrewrite.maven:rewrite-maven-plugin:6.46.1:dryRunNoFork \
-Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:3.42.1 \
-Drewrite.activeRecipes=org.openrewrite.java.migrate.UpgradeToJava25
生成された差分では、new Integer(42) が Integer.valueOf(42) に、System.out.println がJava 25の IO.println に置き換わり、getSecurityManager() の分岐は丸ごと削除され、pom.xml のsource・targetは1.8から25になりました。試して分かった注意点が3つあります。
- MavenをJDK 25で動かすと、JAXBの依存が追加されませんでした。JDK 8で動かしたときだけ
jakarta.xml.bind-api2.3.3とjaxb-runtime2.3.9がpom.xmlに入りました。型を解決できないクラスはレシピの対象から漏れるので、OpenRewriteは移行前のJDKで実行します。 - コンパイルを伴う
dryRunは、JDK 25ではJAXBのコンパイルエラーで止まりました。JDK 25で回すならdryRunNoForkを使います。 - 公式ガイドのコマンドはプラグイン6.50.0を指定していますが、2026年10月19日時点でMaven Centralにあるのは6.46.1まで(rewrite-migrate-javaは3.42.1)で、6.50.0は解決できませんでした。
IO.println への置き換えのように、出力されたコードはJava 25でしかコンパイルできません。ランタイムをJava 25に固める前のステップ2の段階では当てず、ステップ5でターゲットを上げるときに一緒に適用します。
ステップ5:–releaseによるコンパイルターゲットの更新
ランタイムが安定してから javac --release 25 へ上げます。--release は指定した版のAPIだけを参照するようにコンパイラを制約するため、意図せず新しいAPIを使う事故を防げます。なお、Java 25と27の javac で --release 8 を指定すると「ソース値8は廃止されていて、今後のリリースで削除される予定です」と警告されました。Java 8向けにコンパイルし続けられる期間も、いずれ終わります。
ここまで来て、レコードクラスやパターンマッチ、仮想スレッドの仕組みと落とし穴を踏まえた並行処理の書き換えに進めます。module-info.java によるモジュール化はJava 8からの移行では必須ではありません。必要になった段階でJavaモジュールシステムの書き方を参照してください。
移行先の選び方|Java 25を既定にし、21で止める条件
Java 25を既定にする理由
Java 25なら、OracleのPremier Supportが2030年9月以降まで、Temurinが少なくとも2031年9月、Correttoが2032年10月まで更新されます。Spring Bootは3.5.16が25まで、4.0.8と4.1.1が26までを互換範囲にしており、主要フレームワークの対応を待つ必要はありません。新規開発が続くシステムや、5年以上の運用が決まっているシステムはJava 25に置きます。
Java 21で止めてよい条件
Java 21で止める判断が正当化されるのは、依存のなかにJava 25対応版がなく、しかも代替できないものがある場合です。典型は、Spring Boot 2.7から3.x以降へ上げる工数をすぐに取れないケースで、2.7.18の互換範囲の上限はJava 21です。この場合でもTemurin 21は少なくとも2029年12月まで提供されますが、Spring Boot 2.7のOSSサポートは終了済みです。2.7に留まる間の修正版の入手経路と、3.x以降へ移行する期限を別途確保してください。Oracle JDK 21を無償条件で使っているなら、前述の2026年10月の切り替えに合わせて配布元を見直してください。「Java 25は新しすぎて不安」は理由になりません。Java 25はリリースから1年が経ち、25.0.4までアップデートが積み上がっています。21と25で挙動が違う箇所はJava 21と25の違いを実機で比較した記事にまとめています。
Java 27を移行先にしない理由
Java 27は非LTSで、Temurinの提供期限は2027年3月、Correttoの最終更新予定は2027年1月、EOLは2027年4月です。Spring Boot 4.1.1の互換範囲もJava 26までで、Java 27は2026年10月時点で公式の保証範囲に入っていません。Java 29の予定は2027年9月ですが、それを待ってJava 8のまま期限を迎えるより、Java 25へ上げておくほうが安全です。本記事で挙げた非互換をJava 25への移行時に解消しておけば、次回の調査対象を整理できます。ただし、Java 29への移行工数は、今後の仕様変更と依存製品の対応状況を確認して見積もります。
近代化に着手すべきでないケース
すべてのJava 8システムを上げるべきではありません。廃止までの残存期間が移行費用の回収に足りず、必要な保守を確保できるシステムは延命を優先します。ソースコードが失われたシステムは、まずJARのまま移行できる範囲と、改修が必要な範囲を切り分けます。ソース改修が必要なのにソースを回収できない場合は、設定変更や依存ライブラリ更新で対処できる範囲を確認し、移行継続と再構築の費用を比較します。延命を選ぶ場合は、Java 8の更新を受け取れる配布元(Temurin 8やCorretto 8は2030年12月まで)を使いながら、作り直しの計画に切り替えます。残すと決めたら、その理由と再評価の時期を文書に残してください。社内で移行の工数や体制を確保できない場合は、システムマイグレーション・リプレイスの支援のように、棚卸しから移行までを外部に任せる選択肢もあります。レガシー刷新の手法全体はモダナイゼーションの手法と進め方で整理しています。
よくある質問
Java 29はいつリリースされますか?
OracleはJava SE FAQで、Java 25の次のLTSをJava 29として2027年9月に予定しています。6か月ごとの機能リリースの間隔に沿うと、その前に非LTSのJava 28が出ます。いまJava 8から移行するなら、Java 29を待たずJava 25に上げてください。
Java 8のサポート期限はいつまでですか?
配布元によって違います。Temurin 8は少なくとも2030年12月、Corretto 8は2030年12月、OracleのExtended Supportは2030年12月までです。最も早いのはRed HatのOpenJDK 8(RHEL)で、フルサポートは2026年11月30日に終わり、以後は延長サポートになります。期限より先に問題になるのは、ライブラリの修正版がJava 8で動かなくなることです。
Java 8の最新バージョンはいくつですか?
2026年10月19日時点のTemurin 8の最新は8u504-b01です。java -version では 1.8.0_504 のように表示されます。Java 8までは「1.8」と「8」が同じリリースを指す表記で、1.8.0_202 の202が更新番号にあたります。Java 9以降は「1.」の付かない 25.0.4.1 のような形式になりました。
Java 8でコンパイルしたJARはJava 25でそのまま動きますか?
起動できるとは限りません。Java 8のクラスファイル(バージョン52)自体はJava 25のJVMで読めるため、その形式だけを理由とするUnsupportedClassVersionError は出ません。このエラーは逆方向、新しいJDKでコンパイルしたクラスを古いJVMで動かしたときに出ます。落ちる場合の原因は、本文の実測で示したJAXBの削除やリフレクションの制限です。
JDKの移行と同時に、Spring Bootも上げるべきですか?
同じリリースにまとめるのは避けます。Spring Boot 2.7から3.x以降へ上げると javax.* から jakarta.* への置き換えが同時に起き、テストが落ちたときにJDK側とフレームワーク側のどちらが原因か分からなくなります。まずSpring Boot 2.7のままJava 17か21で動かし、安定してからSpring Boot 3.5以上とJava 25へ進む順序が安全です。