the KodeLab

Java バージョン進化史|Java 8 から 25 までの LTS と言語機能の歩み

14,825 文字 38 分で読めます
Java バージョン進化史|Java 8 から 25 までの LTS と言語機能の歩み

高校時代に Java を独学していた頃は、まだ Java 6 / 7 でした。書いていたのは Swing のウィンドウアプリくらいで、ちょっとした関数を渡したいだけでも anonymous inner class をどっさり書く必要があり、いま振り返ると石器時代の道具で家を建てていたような気分です。大学で Java 8 に触れて、初めて list.stream().filter(...).collect(...) のような一行の流れるようなコードを書いたとき、「Java もこんなにきれいに書けるのか」と世界観が一気に開けた感覚がありました。

そこから 2〜3 年に一度新しい LTS が出続け、気がつけば Java 25 まで来ています。本記事では Java 8 → 11 → 17 → 21 → 25 の 5 つの LTS を一気通貫で振り返り、各バージョンが言語に何をもたらしたか、各 JDK ディストリビューションの無償サポート期限はいつまでか、そして 2026 年 3 月に GA したばかりの非 LTS の Java 26 のハイライトまでをまとめます。

本題に入る前に、「LTS」とは何か、Oracle JDK・OpenJDK・Eclipse Temurin・Amazon Corretto などの違いを軽く押さえておきます。詳細は以前 OpenJDK ディストリビューションの選び方 でまとめたので、未読ならそちらを先にどうぞ。要点だけ前提として置いておくと、無償の長期サポートを得たいなら Eclipse Temurin・Amazon Corretto・Azul Zulu のようなコミュニティ/サードパーティのディストリビューションを選ぶこと。Oracle JDK は 17 から NFTC ライセンスで無償商用利用が可能になりましたが、無償期間は次の LTS GA から約 1 年後までで、長期運用の本番環境には向きません。

なぜ LTS を気にするのか

Java は 9 から半年に 1 回のフィーチャーリリース体制(feature release)に変わりました。短期サイクルリリースはセキュリティアップデートが 6 ヶ月だけで、次のバージョンが出ると古い方は終わります。趣味プロジェクトなら気になりませんが、企業の本番環境では辛いです。そこで Oracle が 2018 年に LTS(Long-Term Support) 戦略を打ち出し、特定のバージョンに数年単位のセキュリティアップデートを提供することにしました。OpenJDK コミュニティと主要なディストリビューションも追随し、LTS は企業のバージョン選定の標準解になりました。

LTS リリースのペースは最初 3 年に 1 回(8 → 11 → 17 → 21)でしたが、21 以降は 2 年に 1 回 に短縮されました(21 → 25)。次の LTS 27 は 2027 年 9 月の予定です。短縮の背景は業界からの圧力で、virtual threads や pattern matching といった重要機能を 3 年待たせるのは遅すぎる、ということで LTS の歩幅を狭めた格好です。

5 つの LTS のリリースとサポート期限を、Oracle・Eclipse Temurin・Amazon Corretto に分けて整理しました。3 者で無償期間が大きく異なるためです。

LTSGAOracle PremierOracle 延長Eclipse TemurinAmazon Corretto
82014-032022-03(終了)2030-122030-122030-12
112018-092023-09(終了)2032-012027-102032-01
172021-092026-092029-092027-102029-10
212023-092028-092031-092029-122030-10
252025-09-162030-092033-092031-092032-10

注意点:Oracle JDK 17 / 21 / 25 は NFTC ライセンスで無償商用利用が可能ですが、その無償期間は「次の LTS の GA から約 1 年後まで」しか続きません。たとえば Java 21 の NFTC 無償期間は 2026-09 で終わり、それ以降に Oracle JDK を使うなら Oracle Java SE Subscription を購入する必要があります。Corretto・Temurin などの OpenJDK ディストリビューションはサポート期間中ずっと無償で、違いは維持期間の長さだけです。

Java 8 — すべての始まり

Java 8 は現代 Java の分水嶺です。2014 年にリリースされ、2026 年現在もシェア最大のバージョンであり続けています。エンタープライズの更新が遅いという事情だけでなく、一度に持ち込んだ機能があまりに多かったからでもあります。

  • ラムダ式 — それまで anonymous inner class でひとかたまりだったコードを 1 行に折りたたむ。
  • Stream API — 宣言的なコレクション操作。チェーン可、並列化可。
  • java.time パッケージ — 使い勝手の悪い DateCalendar を置き換える。詳しくは Java 8 日付・時刻 API 入門 にまとめてあります。
  • Optional — 「値が無いかもしれない」という事実を型システムで表現。
  • インターフェイスの default メソッド — インターフェイスが実装を持てるようになり、後の Stream API 進化の前提になった。

Java 8 から 25 まで変わらず動く、典型的な Lambda + Stream の例です。

// 名前のリストから長さ 3 より大きいものを抽出し、大文字に変換、ソートして出力。
List<String> names = List.of("ada", "kyle", "tom", "alice");
names.stream()
     .filter(n -> n.length() > 3)   // ラムダ
     .map(String::toUpperCase)       // メソッド参照
     .sorted()
     .forEach(System.out::println);  // ALICE, KYLE

Java 8 がこれほど長く居座っている理由は、機能自体が十分に使えること、エンタープライズシステムの依存ツリーの深さ、Spring 4 / 5 のロングテール、Android が一時 Java 8 の一部しかサポートしなかったことなどが重なって、アップグレードのモチベーションが薄まっているためです。Oracle Premier Support は 2022-03 に終了しましたが、Eclipse Temurin と Amazon Corretto は 2030-12 まで無償でメンテナンスを続けるので、レガシーシステムが Java 8 のセキュリティアップデートを食い続けることは技術的には可能です。

Java 11 — 9・10 を吸収した整理回

Java 11 は Java 8 のあとの最初の LTS で、9・10 の 2 つの短期サイクルリリースの機能を一括で長期サポート対象に入れた回です。

Java 11 自身の目玉

  • JEP 321 — HTTP Client の標準化。それまで incubator 段階だったものが、11 で java.net.http 正式パッケージに昇格。HTTP/2 と非同期に対応。
  • Java EE と CORBA モジュールを除去(これらの API はすでに陳腐化)。
  • ZGC が実験段階で初登場。
  • 単一ファイル launch:java HelloWorld.java でコンパイルなしに実行可能。スクリプト用途で便利。
  • TLS 1.3。

Java 9(2017-09)から取り込んだもの

  • JEP 261 — モジュールシステム(Project Jigsaw)。JDK 自体がモジュール化され、大規模アプリも module-info.java で依存を宣言できるように。
  • JShell — 公式 REPL。学習や API 検証に便利。
  • List.of()・Map.of() などの不変ファクトリ。Arrays.asList() との違いは Arrays.asList() と List.of() の違い にまとめてあります。
  • G1 がデフォルト GC に。

Java 10(2018-03)から取り込んだもの

  • JEP 286 — var によるローカル変数の型推論var list = new ArrayList<String>(); のように書けて、タイプ量が減る。
  • G1 のパラレル full GC。

ただし Java 11 の吸収成績は半成功どまりでした。モジュールシステムは強力ですが業界の取り込みは遅く、Spring や Hibernate などの主要フレームワークは下位互換のために完全モジュール化せず、結果として 11 にアップグレードした開発者が reflection や JDK 内部 API の制限に頻繁にぶつかりました。Oracle Premier Support は 2023-09 に終了しましたが、Corretto は 2032-01 まで無償なので、Java 11 を継続しても安全性は確保できます。

Java 17 — 12〜16 を吸収、現代 Java の輪郭が固まる

Java 17 は「現代 Java」の輪郭が形になったバージョンで、12〜16 で蓄積された preview 機能を一気に正式化しました。

Java 17 自身の目玉

  • JEP 409 — sealed classes。あるクラスを継承できる相手を制限する仕組みで、pattern matching と組み合わせれば ADT(algebraic data type)の基盤になります。詳細は Java 17 sealed クラス完全解説 にまとめました。
  • JEP 403 — JDK 内部 API の強カプセル化sun.*com.sun.* などの内部 API はデフォルトで reflection アクセス禁止に。古いライブラリのアップグレード時に多くの破壊が発生した変更です。
  • Enhanced Pseudo-Random Number Generators。
  • 新 macOS レンダリング pipeline(Apple Silicon フレンドリー)。

Java 12〜16 から取り込んだ主な正式機能

  • 14JEP 361 — switch 式が正式機能に。switch を式として使え、値を yield できる。switch の歴史全体は別記事の Java 7・17・21・25 から Java 26 まで、Java switch キーワードの進化にまとめました。同バージョンで helpful NullPointerExceptions(NPE メッセージにどの変数が null だったかが含まれる)も追加。
  • 15text blocks 正式、三重引用符の複数行文字列。ZGC・Shenandoah が実験から正式に。
  • 16JEP 395 — records 正式。1 行で immutable なデータクラスを宣言。Lombok とのトレードオフは Java 16 record 入門|record・Lombok・POJO の違いを比較 にまとめました。同時に JEP 394 — pattern matching for instanceof 正式 と Unix-domain socket も追加。

Java 17 までで現代 Java の語彙には sealed・record・pattern matching・text blocks・switch 式が揃い、構文の佇まいは Java 8 とはもはや 2 世代違うものになっています。下は switch 式の例です。

// switch を式として使う — 値を直接返す
String role = switch (level) {
    case 1, 2     -> "junior";          // 複数 case をまとめる
    case 3, 4, 5  -> "mid";
    case 6, 7     -> "senior";
    default       -> throw new IllegalArgumentException("unknown level: " + level);
};

Java 15 で正式化された text blocks は、17 で主流になった構文の代表格で、SQL や JSON、HTML を書くときの文字列連結地獄を消し去りました。

// 三重引用符で開始。中身のレイアウトはそのまま、
// インデントは最少インデント行を基準に正規化されます。
String json = """
        {
          "name": "kyle",
          "role": "engineer",
          "skills": ["Java", "Spring", "Linux"]
        }
        """;

// SQL もぐっと読みやすくなる
String sql = """
        SELECT id, name, created_at
        FROM users
        WHERE status = 'active'
          AND created_at > ?
        ORDER BY created_at DESC
        """;

サポート状況:Oracle Premier は 2026-09、Eclipse Temurin は 2027-10、Corretto は 2029-10 まで。

Java 21 — virtual threads 元年、18〜20 を吸収

Java 21 はここ数年で最も重量感のあるリリースです。15 個の JEP が含まれ、最大の見どころは preview から正式に昇格した virtual threads です。

Java 21 自身の目玉

  • JEP 444 — virtual threads 正式。高並行 IO サービス(HTTP バックエンド、DB アクセス重め)にとっては時代を画す変化で、これまで reactive programming で絞り出していたスループットを、同期コードのまま到達できるようになります。
  • JEP 431 — sequenced collections。List・Deque・LinkedHashSet などに統一の getFirst()getLast()reversed() インターフェイスを追加。
  • JEP 441 — pattern matching for switch 正式。switch が型や record の構造に対してマッチできるように。
  • JEP 440 — record patterns 正式。record のフィールドを直接分解できる。
  • generational ZGC — ZGC に世代分割を追加してスループットを向上。
  • KEM API — ポスト量子暗号への布石。

Java 18〜20 から取り込んだもの

  • 18JEP 400 — デフォルト文字セットを UTF-8 に。見落とされがちですが影響の大きい変更。new FileWriter("a.txt") がプラットフォーム・ロケールごとに違うエンコーディングを使っていた問題が、18 から統一されました。同バージョンで簡易 web server(jwebserver)も追加。
  • 19:virtual threads の第 1 ラウンド preview、structured concurrency が incubator に。
  • 20:scoped values が incubator、virtual threads が第 2 ラウンド preview。

下は virtual threads の例です。書き方はほぼ通常の thread と同じですが、何百万個立てても OS メモリを食い潰しません。

// virtual thread の executor で 10,000 並行 IO タスクを実行。
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            // IO のシミュレーション。HTTP 呼び出しや DB クエリなど。
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}  // executor は自動 close、全タスクの完了を待つ。

これを従来の platform thread でやれば、10,000 スレッドで JVM が押し潰されます。virtual thread に切り替えれば、各タスクのスタックは数 KB 程度で済み、プログラムは余裕で完走します。reactive を書き慣れた人にとっては「ようやく同期で書ける」解放感のある変化です。

JEP 441 が pattern matching を switch に持ち込み、sealed クラスや record と組み合わせると本物の ADT スタイルの分岐が書けるようになります。if-elseinstanceof 強制キャストの層を重ねる必要はもうありません。

// sealed な継承ツリー — Shape を実装するすべてのクラスを列挙する。
sealed interface Shape permits Circle, Square, Triangle {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}
record Triangle(double base, double height) implements Shape {}

// switch が型に対して直接マッチ、コンパイラが網羅性チェックを行う。
double area = switch (shape) {
    case Circle c   -> Math.PI * c.radius() * c.radius();
    case Square s   -> s.side() * s.side();
    case Triangle t -> 0.5 * t.base() * t.height();
    // default 不要 — sealed + 全列挙でコンパイラが保証してくれる。
};

JEP 440 record patterns はさらに踏み込んで、record のフィールドを直接分解できるようにします。getter 呼び出しを大量に省ける書き方です。

record Point(int x, int y) {}
record Line(Point from, Point to) {}

// switch case の中で record を直接分解。ネストした record も分解可能。
String describe = switch (obj) {
    case Point(int x, int y)                       -> "点 (" + x + "," + y + ")";
    case Line(Point(var x1, var y1),
              Point(var x2, var y2))               -> "線分 " + x1 + "," + y1 + " -> " + x2 + "," + y2;
    case null                                      -> "null";
    default                                        -> "不明な形状";
};

Java 21 は LTS のリズム変更の起点でもあり、21 以降は次の LTS が 3 年後(24)ではなく 2 年後(25)になります。サポート状況:Oracle Premier は 2028-09、Temurin は 2029-12 まで。

Java 25 — 22〜24 を吸収、現時点で最新の LTS

Java 25 は 2025 年 9 月に GA、本記事執筆時点で最新の LTS です。JEP は 18 個、21 以降の 2 年で蓄積した機能の正式化と、長らく残っていた荒削りな部分の補完が中心です。

Java 25 自身の目玉

  • JEP 512 — compact source files & instance mainvoid main() だけで実行可能になり、public static void main(String[] args) の様式美から解放されます。新人向けの教材や、使い捨てスクリプト用途に好適。
  • JEP 513 — flexible constructor bodies。コンストラクタが super() 呼び出しの前にバリデーションや前処理を行えるように。「最初の 1 行で必ず親コンストラクタを呼ぶ」制約から解放されます。
  • JEP 519 — compact object headers。オブジェクトヘッダを 96〜128 ビットから 64 ビットに圧縮。大規模アプリの heap メモリを無料で削減できる効能。
  • JEP 510 — KDF APIJEP 509 — JFR CPU-time profiling
  • module import declarationsPEM APIgenerational Shenandoah 正式
  • 32-bit x86 サポートを除去。

Java 22〜24 から取り込んだもの

  • 22JEP 454 — FFM API 正式(Foreign Function & Memory、JNI を置き換える現代的な外部関数呼び出し)、unnamed patterns 正式、stream gatherers が preview、複数ファイルの source launch。
  • 23:ZGC のデフォルトが generational に、Markdown Javadoc。
  • 24JEP 485 — stream gatherers 正式(Stream API にとって Java 8 以来最大の拡張、中間操作を自作可能に)、JEP 484 — Class-File API 正式、JEP 483 AOT class loading、Security Manager の永続無効化、ML-KEM / ML-DSA ポスト量子暗号、JEP 491 — virtual thread synchronization without pinning(Java 21 の virtual thread が synchronized ブロック内で carrier thread に pin されてしまう最大の落とし穴を補修)。

下は Java 25 の instance main、そして Java 24 から正式化された stream gatherers の例です。

// JEP 512 compact source files:このファイルはこの 4 行だけで OK。Hello.java として保存。
// class 宣言、public static void main、import はすべて不要。
void main() {
    println("Hello from Java 25");  // println が直接使える。System.out.println と等価。
}

// 引数を受け取りたい場合は宣言する。使わなければ宣言不要。
void main(String[] args) {
    println("受け取った引数の数:" + args.length);
}

JEP 512 の本当の価値はタイプ量を減らすことではなく、Java の入門ハードルを下げることです。最初の授業で publicstaticString[] args を説明しなくてもロジックに直接入れます。使い捨てスクリプトの用途でも java Hello.java で直接実行できて便利です。

もう一つ試したいのは Java 24 から正式化された stream gatherers で、Stream API にとって Java 8 以来最大の拡張です。これまでは組み込みの filter/map/flatMap などを組み合わせるだけでしたが、独自の中間操作を定義できるようになりました。

import static java.util.stream.Gatherers.windowSliding;
import static java.util.stream.Gatherers.windowFixed;

// スライディングウィンドウ:連続する N 要素ずつ取り、毎回 1 つずつ進める。
var pairs = Stream.of(1, 2, 3, 4, 5)
    .gather(windowSliding(2))
    .toList();
// [[1,2], [2,3], [3,4], [4,5]]

// 固定ウィンドウ:重ならないチャンク。バッチ処理によく使う。
var batches = Stream.of(1, 2, 3, 4, 5, 6, 7)
    .gather(windowFixed(3))
    .toList();
// [[1,2,3], [4,5,6], [7]]

21 から 25 までの 2 年で、Java は virtual threads を仕上げ(pin 問題を解消)、Stream を拡張し(gatherers)、heap を圧縮した(compact headers)。「現代的・高性能な Java」の線がこれで完成しました。サポート状況:Oracle Premier は 2030-09、Temurin は 2031-09、Corretto は 2032-10 まで。

番外:Java 26 — 非 LTS だが現時点で最新

Java 26 は 2026 年 3 月 17 日に GA。LTS ではない(セキュリティアップデートは 6 ヶ月)ものの、本記事執筆時点で最新版なので、覚えておく価値のある目玉をいくつか挙げます。次の LTS 27 でこれらの多くが正式化されるはずです。

  • JEP 517 — HTTP/3 for HTTP Client(正式)。Java 11 で標準化された HTTP Client がついに HTTP/3 と QUIC をサポート、ネットワークスタックがモダンブラウザに追いつきました。
  • JEP 516 — AOT object caching with any GC(正式)。Project Leyden の延長で、起動速度が継続的に改善。
  • JEP 522 — G1 GC throughput improvement(正式)。G1 の同期オーバーヘッドを削減、既存の G1 利用サービスにとって無料の性能向上。
  • JEP 504 — Applet API 除去(正式)java.applet がついに墓場へ。
  • JEP 500 — Prepare to Make Final Mean Final。reflection で final フィールドを書き換える抜け道を絞る、本物の final 化への布石。
  • JEP 525 — Structured Concurrency 第 6 回 preview。21 から preview を続けていまだ正式化されていない、Loom 後で最重要の並行 API。
  • JEP 530 — Primitive types in patterns 第 4 回 preview
  • JEP 529 — Vector API 第 11 回 incubator。まだ incubator。

Java 26 に劇的な新機能はなく、25 で消化しきれなかった preview の継続と、HTTP/3・G1 同期最適化などの実用的な補完が中心です。本番は 25 LTS のままが最も安全ですが、HTTP/3 client は単体で触ってみる価値があります。

アップグレードすべきか?どのバージョンへ?

いまだ Java 8 にとどまっている現場は実は非常に多く、金融システム、古い Spring サービス、レガシーな Android プロジェクト、JVM 上の Scala 2 / Kotlin 1 アプリなどが該当します。これらをすぐ動かす必要は必ずしもありません。Java 8 は Eclipse Temurin・Amazon Corretto 上で 2030-12 まで無償メンテナンスが続くので、セキュリティアップデートは確保されています。ただ業務側で virtual threads・record・pattern matching が欲しくなり始めたら、アップグレードのスケジュールを切る価値があります。

アップグレードする際の原則として:11 や 17 で途中下車せず、21 か 25 まで一気に飛べ。アップグレードのコストは「reflection や内部 API の制限への対応、依存ライブラリの更新、CI フローの更新」といった雑務に集中するので、1 回やるのも 2 回やるのも大差ありません。動かすなら一歩で目的地まで行きましょう。

  • Java 21 へジャンプ:安定性は十分(GA から 2 年以上)、virtual threads が IO 集約サービスにすぐ効く、Spring Boot 3 が完璧にサポート。
  • Java 25 へジャンプ:Java 21 の virtual thread pin 問題は修正済(JEP 491)、stream gatherers でデータ処理がきれいに書ける、compact object headers でメモリ節約。新規プロジェクトは直接 25 で。

フレームワークの互換性も考慮ポイント。Spring Boot 3 は Java 17+、Spring Boot 4 は 21+ を要求する見込みなので、今後 12 ヶ月以内に Spring Boot 4 に移行したいサービスは最低 21 を計画する必要があります。

よくある QA

Q1:LTS は誰が決めている?非 LTS のバージョンは使えるのか?

LTS は Oracle が 2018 年に打ち出した戦略で、OpenJDK コミュニティと主要ディストリビューション(Temurin・Corretto・Zulu)が追随しています。非 LTS バージョン(22・23・24・26 など)はセキュリティアップデートが 6 ヶ月だけで、長期運用のサービスには向きません。新しいもの好きなプロジェクトや、ライフサイクルの短い案件向けです。開発・実験・デモ用としてはまったく問題ありません。

Q2:無償の OpenJDK と Oracle JDK の違いは?

機能面ではほぼ同じです(Oracle JDK と OpenJDK は同じソースベースを共有)。違いは主にライセンスとサポート期間で、詳細は OpenJDK ディストリビューションの選び方 に書きました。要点は、無償の長期サポートが欲しいなら Temurin・Corretto・Zulu を選び、Oracle Java SE Subscription を購入していない限り Oracle JDK は本番環境では使わない、ということです。

Q3:アップグレードでよく踏む地雷は?

  • Java 8 → 11:モジュールシステム(JPMS)が多くの reflection や JDK 内部 API をブロック、古いライブラリが直接壊れる。
  • Java 11 → 17:JEP 403 で JDK 内部 API が強カプセル化、reflection を使うコードがさらに壊れる。--add-opens で逃がすか、17 対応のライブラリにアップデートする必要あり。
  • Java 17 → 21:deprecated API を乱用していなければ比較的スムーズ。
  • Java 21 → 25:32-bit x86 サポート除去、Security Manager の永続無効化、いくつかの細かい API 削除に注意。

Q4:virtual threads は Java 21 が初出?

そうです。ただし Java 19 で preview デビューし、21 で正式化されました。Java 25 でさらに仕上げ(JEP 491 が synchronized ブロック内で carrier thread に pin される問題を解決)。IO 集約サービス(HTTP バックエンド、DB アクセス重め)を書いているなら、virtual threads はここ数年で最も実感しやすいアップグレード理由です。

Q5:Java 21 と 25 はどちらを選ぶ?

新規プロジェクトは 25 で直接。既存プロジェクトが 21 で安定して動いているなら、25 のパッチリリースが落ち着くまで半年〜1 年待ってからアップグレードする手もあります。25 の無償サポート期間のほうが長い(Corretto で 2032-10 まで)ので、長期的には 25 が有利です。

Q6:JDK 内蔵の HTTP Client は OkHttp や Apache HttpClient を本当に置き換えられる?

Java 11 で標準化された HTTP Client(JEP 321)は HTTP/2・非同期・リアクティブに対応、Java 26 では HTTP/3 まで追加されました。日常的な REST 呼び出しなら十分です。ただしエコシステムの成熟度(インターセプタ、メトリクス、retry policy、認証パッケージ)では現時点でも OkHttp と Apache がリードしているので、複雑な統合では結局サードパーティに戻ることもあります。

Q7:LTS が 2 年に短縮されたのは良いことか悪いことか?

開発者個人にとっては良い話です。virtual threads が 19 preview → 21 正式までわずか 2 年で、新機能が早く LTS に入り、フレームワークやエコシステムも追随しやすくなります。企業にとってはプレッシャー:アップグレードのリズムがきつく、予算とテスト人員も追いつく必要があります。総合的には、Go・Rust・Kotlin といった速いペースの言語に Java が追いつくために必要な動きです。

まとめ

3 つに絞ります。

  1. Java 8 から 25 までの 11 年で、言語は OOP 中心から「OOP + Functional + Pattern Matching + 新しい並行モデル」の総合体系に進化しました。現代 Java の語彙は Java 8 とは 2 世代違う。
  2. LTS は企業のバージョン選びの安全網ですが、Oracle JDK と OpenJDK ディストリビューションでは無償サポート期間が大きく異なります。長期の本番運用には Eclipse Temurin・Amazon Corretto・Azul Zulu を。
  3. まだ Java 8 / 11 を使っているサービスでアップグレードを考えるなら、21 か 25 まで一気に飛ぶのを推奨。17 への移行は今となってはお得感が薄い。新規プロジェクトに包袱がなければ 25 で。

高校時代の Java 6 / 7 で anonymous inner class を書いていた頃から、いま Java 25 で virtual thread + record pattern を書くまで、この時間軸を眺めると言語の活力が確かに見えます。Java は決して書いていて一番カッコいい言語ではありませんが、進化の方向はずっと実用的で、開発者が実際に踏む痛点を一つずつ潰してきました。次の LTS 27 は 2027 年 9 月の予定で、その頃には structured concurrency、primitive patterns、文字列テンプレートなどの preview が正式化されているはずです。引き続き楽しみに。

参考資料: