15 人が閲覧(直近 30 日) アーキテクチャ

Java近代化の進め方|Java 8をJava 25へ上げる判断基準と4ステップ

Java近代化の進め方|Java 8をJava 25へ上げる判断基準と4ステップ

Oracle JDK 17 のPremier Supportは2026年9月に終わります。ただしこれは「Java 17が止まる日」ではありません。Oracleは同じロードマップの脚注で2026年10月から2029年9月までExtended Supportの費用を免除すると明記していますし、Eclipse Temurin 17は少なくとも2027年10月まで無償で更新が続きます。2026年9月に起きるのは停止ではなく、どの配布元にいくら払うかを選び直す期限が来ることです。この記事では、2026年8月時点のバージョンとサポート期限を整理したうえで、Java 8から上げるときにぶつかる4つの非互換、黙って挙動が変わる箇所、実際の移行手順、そしてJava 21で止めるかJava 25まで上げるかの判断基準を、一次情報に基づいて示します。

まとめ

結論から言えば、Java 8の資産は「Java 25へ一気に書き換える」のではなく「ランタイムを先に上げてから、コンパイルターゲットを後から上げる」順序で進めるのが現実的です。移行を止めるのは自社コードの書き換え量ではありません。Java 11で削除されたJava EEモジュール、javax.* から jakarta.* への名前空間変更、JDK 24でのSecurity Manager恒久無効化、そして sun.misc.Unsafe のメモリアクセス禁止という4点で、いずれも依存ライブラリの奥に潜んでいます。

移行先はJava 25を既定とし、依存ライブラリがJava 25に追いついていない場合に限りJava 21で止めます。Java 17を移行先に選ぶのは2026年時点では勧められません。着地した時点でPremier Supportの期限を越えているためです。まずは jdeps と jdeprscan を既存のJARに当てて、壁がどこに何本あるかを数字にするところから始めてください。以下、根拠と手順を順に見ていきます。

Javaエコシステムの現在地|バージョン・LTS・サポート期限(2026年8月時点)

現行LTSはJava 25、最新の機能リリースはJava 26

Eclipse Adoptiumが公開しているリリース情報APIによると、2026年8月時点でLTS(長期サポート)に指定されているのはJava 8・11・17・21・25の5系統、最新の機能リリースはJava 26、最新のLTSはJava 25です。同じくAdoptiumのサポートロードマップは、無償ビルドであるTemurinの更新提供期限を次のように公表しています。

バージョン GA LTS Temurinの無償更新
Java 8 2014-03-18 LTS At least Dec 2030
Java 11 2018-09-25 LTS At least Oct 2027
Java 17 2021-09-14 LTS At least Oct 2027
Java 21 2023-09-19 LTS At least Dec 2029
Java 25 2025-09-16 LTS At least Sep 2031
Java 26 2026-03-17 非LTS 次リリースまで

非LTSであるJava 26は、次の機能リリースが出た時点でアップデートの提供が止まります。実質的な寿命が半年なので、業務システムの移行先に選ぶバージョンではありません。Java 26に何が入ったかはJava 26で押さえるべき10個のJEPで個別に扱っています。

Oracleのサポート期限から逆算した移行の締め切り

有償サポートを契約している場合、締め切りを決めるのはOracleのロードマップです。各LTSのPremier SupportとExtended Supportの終了時期は次のとおりです。

バージョン 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月

この表は脚注まで読む必要があります。Premier Supportの終了時期にはOracle自身が「Or later(またはそれ以降)」と留保を付けており、Java 17については2026年10月から2029年9月までExtended Supportの費用を免除すると明記されています。さらにExtended Support終了後もSustaining Supportは無期限に継続します。つまり「期限が来たら一斉に何かが止まる」構造ではありません。

それでも移行先をJava 17に置くべきではありません。Oracleは次期LTSをJava 29として2027年9月にリリースする計画を公表しており(LTS指定と日付は変更の可能性あり)、LTSは2年間隔で更新されていきます。いまJava 8からの移行を計画してJava 17に着地させると、その時点で既にPremier Supportの期限を越えています。ライセンスと配布形態の全体像はJDK・JRE・JVMの違いとOracle Java/OpenJDKのライセンスで整理しています。

言語シェアとAI用途の広がり

「Javaは古い」という評価は、指標とは食い違います。TIOBE Indexの2026年8月版でJavaは4位、レーティングは8.25%でした。前年同月比では0.34ポイント下げていますが、Python・C・C++に続く位置で、上位圏から外れる動きは起きていません。

用途の広がりも数字に出ています。Azulが2026年2月10日に公表した State of Java Survey & Report(Dimensional Research実施、5大陸の2,039名が回答)では、JavaでAI機能を実装している企業が62%に達し、前年の50%から12ポイント増えました。近代化への投資は延命ではなく、新規開発をその資産の上で行うための前提整備として位置づけるのが実態に合っています。

Java 8のまま止まった資産が抱えるコスト

Oracle Javaのライセンス費用と監査リスク

Java 8を動かし続けること自体より先に、コストとして表面化しているのはライセンスです。前掲のAzul調査では、Oracle Javaの価格に懸念を示した回答者が92%。Oracle Javaの少なくとも一部を非OracleのOpenJDKディストリビューションへ「移行済み・移行中・移行予定」と答えた組織が81%あり、そのうえでJava資産の全体を移行する意向を示した組織が63%でした。移行理由の内訳はコストが37%、オープンソース志向が31%、Oracleの方針変更に伴う不確実性が29%、監査リスクが26%と続きます。すでにOracleの監査を受けたと回答した組織は21%ありました。

多くの現場では「バージョンを上げる」判断と「配布元を変える」判断が同時に走っている、ということです。Eclipse TemurinやAmazon Correttoといった非Oracleビルドを選べばライセンス費用の問題は切り離せるため、バージョン移行と配布元の変更は同じプロジェクトで一度に片づけたほうが手戻りが少なくなります。どこまでが無料でどこから有償かはOpenJDKの商用利用とライセンスの範囲で条件を確認できます。

ライブラリ側の打ち切りによる連鎖的な停滞

Java 8に留まると、自社コードが動くかどうかとは無関係に、周辺のエコシステムから切り離されます。Spring Bootの公式System Requirementsによれば、4.1.0はJava 17以上を要求し、Java 26まで対応します。Java 8で動くのはSpring Boot 2.x系までなので、3.x系以降に上がれない限り、新しいライブラリもセキュリティ修正も届きません。

この影響は脆弱性対応の速度に直結します。CVEが公表されたとき、対応版がJava 17以上を前提としていれば、パッチを当てるためにまずランタイム移行が必要になります。障害対応の最中にJDKのバージョンアップを始めることになる。これが最大のリスクです。

Java 8から上げるときにぶつかる4つの非互換

移行の工数を押し上げるのは、業務ロジックの書き換えではありません。Java 9以降にプラットフォーム側で起きた4つの非互換な変更が、依存ライブラリの奥で引っかかります。順に見ていきます。

JEP 320で削除されたJava EE・CORBAモジュール

Java 11で、JEP 320によりJava EEとCORBAのモジュールがJDK本体から削除されました。Java 9の時点で削除予定として非推奨化されていたものです。Microsoft Learnの移行ガイド(2026年6月15日更新)は、削除されたモジュールと推奨される代替依存を次のように対応づけています。

削除されたモジュール 技術 推奨される代替依存
java.xml.bind JAXB org.glassfish.jaxb:jaxb-runtime
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

これらに加えて、6モジュールを束ねるアグリゲータの java.se.ee と、wsgen・wsimport・schemagen・xjc といったツールを含む jdk.xml.ws・jdk.xml.bind も同時に削除されています。Java 8ではJDKに同梱されていたため、依存関係を宣言せずに javax.xml.bind.JAXBContext を使っているコードが珍しくありません。

症状の出方は状況で変わります。Java 8でコンパイル済みのJARをJava 11以降で実行すると NoClassDefFoundError で落ちます。ソースを再コンパイルする場合はコンパイルエラーとして表面化するので、そこで気づけます。厄介なのはリフレクションやServiceLoader経由で参照している箇所で、これはコンパイルを通り抜け、起動時まで表面化しません。Microsoft Learnも「jdeprscan と jdeps はリフレクション経由のアクセスを警告できない。最終的にはJava 11で実行して確かめるしかない」と明記しています。

javax.* から jakarta.* への名前空間変更

2020年12月8日にリリースされたJakarta EE 9で、パッケージの名前空間が javax.* から jakarta.* へ変更されました。これはJDKのバージョンとは独立した、Jakarta EE側の破壊的変更です。Spring 6.0以降、Hibernate 6.0以降、Jersey 3.0以降がこの新しい名前空間を採用しています。

ここが厄介なのは、JDKを上げただけでは起きず、Spring Boot 3系へ上げた瞬間に一斉に発生する点です。import文の機械的な置換で済む部分が大半ですが、リフレクションでクラス名を文字列指定している箇所や、XMLの設定ファイル、アノテーションプロセッサの生成コードは置換から漏れます。JDK移行とJakarta EE移行を同じリリースに詰め込むと、どちらの変更で落ちているのか切り分けられなくなります。段階を分けてください。

JDK 24で恒久無効化されたSecurity Manager

Oracleの公式ドキュメント「The Security Manager Is Permanently Disabled」によると、JDK 24以降、Security Managerは恒久的に無効化され、将来のリリースでAPI自体が削除されます。起動時に -Djava.security.manager を disallow 以外の値(無指定・空文字・allow・default・カスタムクラス名)で指定するとJVMは初期化に失敗し、「A command line option has attempted to allow or enable the Security Manager.」というエラーで終了します。実行時に System.setSecurityManager() を呼ぶと UnsupportedOperationException が送出され、System.getSecurityManager() は常に null を返します。

移行前の確認には -Djava.security.manager=disallow が使えます。これはJDK 18以降の既定値で、指定しても起動は失敗しません。Oracleのドキュメント自身が事前テストの手段として挙げています。自社コードでSecurity Managerを使っている例は多くありませんが、アプリケーションサーバーやプラグイン機構を持つ製品が内部で使っているケースがあります。代替はJDKの中にはなく、Oracleが挙げているのはコンテナやハイパーバイザーによる隔離、そしてmacOS App Sandboxやseccompといったコード外の機構です。サンドボックス的な分離をJVM内で完結させていた設計は、Java 24以降では成立しません。

JDK 26で例外になる sun.misc.Unsafe のメモリアクセス

4つのうち、2026年に新しく効いてくるのがこれです。Oracleのinside.javaが2025年1月に公開した整合性方針の解説によると、sun.misc.Unsafe のメモリアクセスメソッドは次の段階で無効化されます。

JDK --sun-misc-unsafe-memory-access の既定 挙動
23 allow 非推奨の警告のみ
24 warn 実行時に警告を既定で出力
26以降 deny 使用のたびに例外を送出
28以降 (削除) メソッド自体を削除

問題は、このAPIを直接呼んでいるのがほぼ確実に自社コードではないことです。シリアライズ系やバイトコード操作系のライブラリが内部で使っており、古いバージョンを固定したまま抱え込んでいると、deny が既定になった環境では起動しなくなります。JDK 24で warn のまま一度動かして警告を採取しておくと、どのライブラリが該当するかを事前に特定できます。代替はオンヒープが java.lang.invoke.VarHandle(JDK 9で追加)、オフヒープが java.lang.foreign.MemorySegment を中心とするForeign Function & Memory API(JDK 22で正式機能)です。

壁ではないが黙って挙動が変わる4点

非互換で落ちるものは気づけます。厄介なのは、落ちずに結果だけが変わるものです。Microsoft Learnの移行ガイドが挙げている代表例は次の4つで、いずれもテストが通っても本番で表面化します。

  • 既定のガベージコレクタが変わる。Java 8のParallel GCに対し、Java 9以降の既定はG1GCです。Java 8と同条件で比較するには -XX:+UseParallelGC を明示します。
  • ロケールデータの既定がJEP 252でCLDR(Unicode ConsortiumのCommon Locale Data Repository)に変わり、日付や数値の書式が変化します。Java 8の挙動に戻すにはシステムプロパティ java.locale.providers=COMPAT,SPI を指定します。
  • システムクラスローダーを URLClassLoader にキャストしていたコードが ClassCastException を投げます。実行時にクラスパスを差し込む処理を持つアプリケーションで発生します。
  • GCログのオプションがJEP 271で作り直されており、Java 8の書式のまま起動すると認識されないオプションとしてJVMが終了します。起動スクリプトのフラグは移行前に洗い出してください。

Java 8との比較で性能を評価するなら、GCの設定を揃えないと数字が意味を持ちません。移行直後にGCのチューニングまで同時に試すのは避け、まず同条件で動くことを確認してから調整に入る順序が安全です。

近代化の実行手順|壊さずに上げる4ステップ

Oracleのマイグレーションガイド(JDK 25版)は、移行準備として「新しいJDKでまず実行する」「ツールと外部ライブラリを更新する」「最新のJDKコンパイラでコンパイルする」「jdeps を実行する」の4点を挙げています。これは番号付きの厳密な手順ではなく箇条書きの提案なので、本記事では実行順に組み替えて示します。狙いは共通していて、コードを書き換える前に、書き換えが必要な箇所を確定させることです。

ステップ1:jdeps と jdeprscan による棚卸し

既存のJARに対して、JDK内部APIへの依存と非推奨・削除APIの使用箇所を静的に洗い出します。どちらもJDKに同梱されているツールで、追加インストールは不要です。Microsoft Learnが強調しているとおり、再コンパイルせずに既存のJARへ直接当てられるため、サードパーティのライブラリも含めて評価できます。

# JDK内部API(sun.* など)へのクラスレベル依存を検出する
# 多重リリースJARを含む場合は --multi-release を付ける
jdeps --jdk-internals --multi-release 25 --class-path libs/log4j-core.jar app.jar

# 非推奨APIを最も網羅的に洗う(--release に実行中JDKのバージョンを指定する)
jdeprscan --release 25 app.jar

# 優先度を付けたいときはJava SE 8時点の非推奨APIに絞る
jdeprscan --release 8 app.jar

# 削除予定として非推奨化されたAPIの一覧そのものを確認する
jdeprscan --release 25 --list --for-removal

jdeps の書式は jdeps [options] path ... で、--jdk-internals は -p・-e・-s と併用できません。jdeprscan の書式は jdeprscan [options] {dir|jar|class} で、--release には 6・7・8 と、9から実行中のJDKのバージョンまでを指定できます。ここで注意が要るのは --for-removal で、--release に 6・7・8 を指定した場合は併用できません。削除予定APIを絞り込むときは実行中のJDKのバージョンを指定してください。--release 9 のような古い値を指定すると、Java 10以降に削除予定となったAPIを取りこぼします。クラスパスの指定は --class-path だけが有効で、他の表記は動きません。ここで出た件数が、そのまま移行の見積り根拠になります。

ステップ2:再コンパイルせずランタイムだけ先に上げる

Javaのクラスファイルは上位互換なので、Java 8でコンパイルした成果物はJava 25のJVMでそのまま動きます。最初のステップでは javac のターゲットを変えず、実行するJDKだけを差し替えてください。これで「JDKを上げたこと自体で壊れるもの」と「新しい文法を使ったせいで壊れるもの」を切り分けられます。

この段階で表面化するのが、前章までの非互換と挙動変化です。削除されたJava EEモジュールと sun.misc.Unsafe はここで落ちます。JDK 24以降を使うなら --sun-misc-unsafe-memory-access=warn を明示して、警告をログに残した状態で回帰テストを流してください。

ステップ3:ライブラリとフレームワークの底上げ

ステップ2で特定した依存ライブラリを、新しいJDKに対応したバージョンへ上げます。この作業がJDK移行の工数の大半を占めます。Microsoft Learnは、ライブラリの更新は別の作業として切り出し、変更を最小限に保つことを推奨しています。すべてを一度に最新化すると、エラーの原因がライブラリ更新なのかランタイム変更なのか判別できなくなるためです。

ビルドツール自体も前提を満たす必要があります。Spring Boot 4.1.0の場合、Java 17以上に加えてSpring Framework 7.0.8以上、Maven 3.6.3以上、Gradle 8.14以上または9.x、Servlet 6.1対応のTomcat 11.0.xまたはJetty 12.1.xが要求されます。CIで固定しているビルドツールが古いまま、という理由で足止めされる例は少なくありません。フレームワーク側の変更点はSpring Boot 4とSpring Boot 3との違いで確認できます。

ステップ4:--release でコンパイルターゲットを引き上げる

ランタイムが安定してから、コンパイルターゲットを上げます。javac の --release オプションを使うと、指定したバージョンのAPIだけを参照するようにコンパイラが制約をかけるため、意図せず新しいAPIを使ってしまう事故を防げます。

ここまで来て初めて、レコードクラスやパターンマッチ、仮想スレッド(Virtual Thread)の仕組みと落とし穴といった新機能を使えるようになります。逆に言えば、ステップ1から3を飛ばして新機能の適用から入ると、動かない原因が自社の書き換えなのか依存ライブラリなのか判別できません。module-info.java によるモジュール化はさらに後の工程で、Java 8からの移行では必須ではありません。必要になった段階でJavaモジュールシステムの構成方法を参照してください。

移行先バージョンの選択基準|Java 21とJava 25の判断分岐

Java 25を選ぶべき条件

既定はJava 25です。Oracleの契約ではPremier Supportが2030年9月まで、Temurinなら少なくとも2031年9月まで更新が届きます。GA済みのLTSのなかでは、いま移行を計画するプロジェクトが次の移行を考えずに済む唯一の選択肢です。フレームワーク側の対応も揃っており、前掲のとおりSpring Boot 4.1.0はJava 26まで動作保証しているため、Java 25は完全に射程内にあります。主要フレームワークの対応待ちを理由にJava 25を見送る根拠は、2026年8月時点では見当たりません。新規開発が続くシステム、5年以上の運用が確定しているシステムは、迷わずJava 25に置いてください。

Java 21で止めてよい条件

Java 21で止める判断が正当化されるのは、依存ライブラリのなかにJava 25対応版が存在せず、かつそれが代替不能な場合だけです。Java 21のPremier Supportは2028年9月まで、Temurinの更新は少なくとも2029年12月まで続くので、猶予は2年以上あります。商用パッケージ製品や特定ハードウェア向けのドライバライブラリを組み込んでいるシステムでは、この制約が現実に発生します。

逆に、「Java 25は新しすぎて不安だから」という理由でJava 21を選ぶのは誤りです。Java 25は2025年9月のリリースから1年近く経過し、LTSとしてのアップデートも積み上がっています。バージョンの新しさへの漠然とした不安を、サポート期限という具体的な期限より優先させないでください。

移行の優先順位|基幹システムを先に、Androidとデスクトップは別管理

複数のシステムを抱えている場合、着手順は資産の性質で決まります。優先度が最も高いのは基幹業務システムです。Azulの調査で企業の62%がJavaでAI機能を実装していると回答しているとおり、新規開発は既存のJava資産の上に積まれます。ここを上げないと、新しい機能がすべて別システムとして外側に積み上がり、連携部分が複雑になっていきます。

一方、AndroidアプリのJavaはAndroid SDKが定めるAPIレベルに従うため、JDKのバージョン移行とは別の管理系統になります。この記事の手順をそのまま適用する対象ではありません。デスクトップGUI資産も、JDKを上げれば動作しますが、UIツールキットの選択という別の判断が絡みます。現状はJava Swingの現在地とAWTとの違いとJavaFXとSwingの選択基準で個別に扱っています。

近代化に着手すべきでないケース

すべてのJava 8システムを上げるべきではありません。3年以内に廃止が決まっているシステムと、ソースコードが失われてJARしか残っていないシステムは、移行の対象から外す判断が合理的です。とくに後者は、ステップ1の jdeprscan で問題箇所を特定できても修正する手段がないため、工数の見積り自体が成立しません。外部ネットワークから完全に隔離され入力データの経路が固定されているバッチ処理も、優先度を大きく下げてかまいません。

この場合の代替策は、隔離の強化とリプレース計画への切り替えです。Java 8のまま残す判断をするなら、その決定と理由、そして再評価の時期を文書に残してください。判断を記録しないまま放置した結果が、いま多くの組織が抱えている「誰も理由を説明できないJava 8」です。

よくある質問

Java 1.8とJava 8は同じものですか?

同じリリースを指します。Java 8までのバージョン文字列は 1.8.0_202 のように 1.x 形式で、製品名の「8」と内部表記の「1.8」が併存していました。Java 9のJEP 223がこの二重表記を廃止し、JDK 10以降はJEP 322が定める $FEATURE.$INTERIM.$UPDATE.$PATCH 形式で、末尾のゼロを省いて 25.0.1 のように表記されます。移行時に確認すべきなのは、ビルド設定に 1.8 と書かれた source や target の指定が残っていないかです。これが残る限り、実行するJDKを新しくしてもコンパイル結果はJava 8向けのままです。

Java 8でコンパイルしたJARをJava 25で実行すると UnsupportedClassVersionError になりませんか?

なりません。このエラーは逆方向、つまり新しいJDKでコンパイルしたクラスを古いランタイムで実行したときに出ます。クラスファイル形式のバージョンはJava 8が52、Java 11が55と1つずつ上がっていき、JVMは自分より新しい形式を読めないためです。Java 8のJAR(形式52)はJava 25のJVMで問題なく読み込めます。落ちる場合の原因は形式のバージョンではなく、削除されたJava EEモジュールや sun.misc.Unsafe への依存です。

JDKの移行と同時に、Spring Bootのバージョンも上げるべきですか?

同じリリースにまとめるのは避けてください。Spring Boot 4.1.0はJava 17以上を要求しJava 26まで対応するため、JDKを上げること自体は前提を満たします。問題はSpring Boot 3系への移行で javax.* から jakarta.* への名前空間変更が同時に発生する点です。両方を一度に実施すると、テストが落ちたときにJDK側の非互換なのかJakarta EE側の置換漏れなのかを切り分けられません。JDK移行を先に完了させ、安定を確認してからフレームワークを上げる順序を推奨します。

Javaはいまどんなシステムで使われていますか?

中心は企業の基幹業務システムです。Azulが2026年2月に公表した調査(回答者2,039名)では、JavaでAI機能を実装している企業が62%と前年の50%から増えており、既存の業務システムの上に新しい機能が積まれている状況が読み取れます。Webアプリケーションの領域ではSpring Bootが標準的な選択肢です。このほかAndroidアプリはAndroid SDKの管理系統で動き、デスクトップGUIではSwingとJavaFXが使われ続けています。移行の考え方がそれぞれ違うため、資産ごとに分けて計画してください。

Java 8のままでも動いているなら、そのまま使い続けてはいけませんか?

動作が止まるわけではありません。Eclipse Temurin 8なら少なくとも2030年12月まで無償でセキュリティ修正が届きますし、Oracleと契約するならExtended Supportが同じく2030年12月まで続きます。止まるのはOracleとの契約であって、Java 8そのものではありません。判断を分けるのは、脆弱性が公表されたときに何が起きるかです。修正版のライブラリがJava 17以上を要求していれば、パッチを当てる前にJDK移行から着手することになります。障害対応の最中にバージョンアップを始める事態を避けるため、廃止予定が3年以内に確定しているシステムを除いて移行計画を立ててください。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.09 テックブログ IDCFクラウド(IDCフロンティア)不正アクセス・ランサムウェア:影響先・復旧・データは戻るか
  2. 2026.10.08 テックブログ 大阪公立大学のランサムウェア被害と仮想化基盤の停止|全授業休講に至った経緯とバックアップを守る設定
  3. 2024.11.08 テックブログ OpenAPI GeneratorでJavaコードを自動生成する方法|CLI導入からSpring・ライブラリ選択まで
  4. 2026.10.09 テックブログ ニッスイのサイバー攻撃で日水物流の入出荷停止|委託先クラウド障害に荷主が備える手順
  5. 2026.10.09 テックブログ 京王電鉄のランサムウェア被害とグループ共通基盤:決済・ポイント・予約が止まった範囲と遮断の初動

RELATED POSTS 関連記事

目次