- JAVA
- 技術 💻
Javaバージョン別まとめ【2026年9月版】8〜27の特徴と注意点
Javaって、バージョンによって書けることも、気をつけたいことも変わるんですよね。しかも現場では、8が現役で動いていたり、17や21が主力だったり、25への移行を検討していたりと幅が広い。
今回は、現場でよく使われている世代から最新まで、特徴とその世代ならではの心得をセットで並べました。8月に一度まとめたものを、9月15日に出たJava 27を含めて2026年9月26日時点に更新しています。移行判断に使える形で整理したつもりです。異論・追加も大歓迎です。
まず、いまの位置関係から
2026年9月26日時点の状況です。
| 区分 | バージョン | リリース |
|---|---|---|
| 最新のLTS | Java 25 | 2025年9月 |
| 最新のフィーチャーリリース | Java 27 | 2026年9月15日 |
| 次のLTS | Java 29 | 2027年9月(予定) |
Javaは3月と9月の年2回リリースで、LTSは現在2年ごと(25の次は29)。最新版と最新LTSは別物なので、ここは混同しないようにしたいところですね。
現場で多いのはJava 17と21です。8で動き続けているシステムも数多くあり、25への移行を検討し始めたチームも増えてきました。どの世代にも、それを支えてきた人と理由があります。順に見ていきます。
Java 8 ── いまも現場を支えている、書き方を変えた世代
2014年リリース。Javaの書き方そのものを変えたバージョンです。ラムダ式。Stream API。Optional。新しい日付時刻API(java.time)。いまでは当たり前に使っているものが、ここで一気に入りました。12年経った今も多くの業務システムが8で動いているのは、この世代の完成度の証でもあります。
なぜ現役なのか。依存ライブラリの対応、安定して動いているものを守る判断、検証工数の兼ね合い。動き続けているシステムには、それを止めずに支えてきた人がいます。「古い」の一言で片づけられる話ではないんですよね。
この世代の心得。8で書き続けるなら、押さえておくと得なところがいくつかあります。
ループ内での文字列連結。大量の文字列をループの中で + で連結する場合は、StringBuilderを使ったほうが効率的になるケースがあります。ひとつ補足すると、Java 9以降は文字列連結の実装そのものが変わっていて、単純な + が必ず昔ながらの形に展開されるわけではありません。なのでこれは、Java 8を対象にした心得として読んでください。
parallelStream() の使いどころ。並列化には、分割して束ねるための準備が必要です。その手間が処理そのものより大きい場合、逆に遅くなります。しかも既定では全体で共有されるスレッドプールを使うので、他の処理に影響することもあるんですよね。
int と Integer の混在。ボクシングとアンボクシングが繰り返されると、不要なオブジェクト生成が発生し、性能やメモリに影響する場合があります。ただし Integer には一定範囲のキャッシュがありますし、JVMの最適化も効きます。常に遅くなるわけではないので、気になるなら実測するのが確実です。
Optional の使いどころ。Optionalは主に「値が存在しない可能性」を戻り値で表現する用途に向いています。フィールドや引数に使うことが禁止されているわけではありませんが、多用するとAPI設計やシリアライズとの相性で扱いにくくなる場合があります。
Java 11 ── 8からの最初の乗り換え先
2018年リリース。8の次のLTSとして、多くのプロジェクトが移った先ですね。
Java 11までに使えるようになった、代表的なもの。ローカル変数の型推論(var)はJava 10で導入。標準のHTTPクライアントはJava 9でインキュベータとして入り、11で正式化。String の便利メソッド(isBlank、strip、repeat、lines)は11で追加。「11で入った」と一括りにされがちですが、積み上がってきたものなんですよね。
この世代の心得。var の使いどころですね。型が推論できても、読む人が推論できるとは限らないんです。右辺から型が明らかなときだけにするのが無難かなと。あとは移行時の話で、8で使っていた一部のAPIが削除されています。ここは事前確認が要ります。
Java 17 ── 言語がまとめて進んだ世代
2021年リリース。現場でいちばん多い世代のひとつで、言語仕様がまとめて進んだバージョンです。
Java 17までに揃った、代表的な言語機能。ここもまとめて「17で入った」と語られがちですが、実際は積み上がってきたものです。
- switch式 ── Java 14で正式化
- テキストブロック ── Java 15
- record ── Java 16
- instanceof のパターンマッチング ── Java 16
- sealed classes ── Java 17
switch が式になったことで、break忘れによる意図しない流れ込みが起きなくなりました。値を返す形で書けるので、変数の宣言と代入が分かれないのも大きいですね。Java 17自身の変更として大きいのは、sealed classesの正式化と、JDK内部APIの強いカプセル化です。後者は移行時に効いてきます。
この世代の心得。「遅くなる」というより「壊れる」側の話で、recordの中に可変なものを入れることです。
record Order(String id, List<Item> items) {}
これ、items のリスト自体は差し替えられませんが、中身は書き換えられます。recordが保証するのは浅い不変性まで。完全に不変にしたいなら、コンストラクタでコピーして防御する必要があるんですよね。HashMapのキーに使うときは特に注意が要ります。中身が変わると equals や hashCode の結果も変わってしまうので、取り出せなくなります。
移行時の注意。内部APIへのアクセスが強く制限されました。リフレクションで無理やり触っていたライブラリが動かなくなることがあるので、依存の確認は必須です。
Java 21 ── 仮想スレッドが来た世代
2023年リリース。並行処理の書き方が変わったバージョンです。RJCでも金融業界向けのプロジェクトなど、堅い業務システムの土台として使っています。
入ったもの。仮想スレッド。switchのパターンマッチング。recordパターン。Sequenced Collections。世代別ZGC。仮想スレッドは、I/O待ちが多い処理向けの機能ですね。「1リクエストに1スレッド」という素直な書き方のまま、数万〜数百万のスレッドを扱えるようになりました。
ここが最大の心得です。Java 21〜23では、synchronized の中でブロッキングすると、スケーラビリティを損なう可能性があります。仮想スレッドは、待っている間に土台のスレッド(キャリアスレッド)を他に譲る仕組みなんですが、synchronized の中だとこれができません。土台のスレッドに固定されてしまう。これをピン留め(pinning)と呼びます。
動作として間違いになるわけではないんです。ただ同時実行数が増えたときに、伸びなくなるんですよね。Java 21〜23を使っていて、I/Oを含むクリティカルセクションがあるなら、ReentrantLock への置き換えを検討する場面かなと思います。
そして朗報です。Java 24で、synchronized による主要なピン留め問題は解消されました。ブロックしてもキャリアスレッドを解放するようになっています。なのでJava 24以降では、ピン留めの回避だけを理由に機械的に ReentrantLock へ置き換える必要はありません。ただし「ほぼすべてのケースで」という位置づけなので、ネイティブメソッドの呼び出しなど、別の要因によるピン留めは残ります。
他の心得。仮想スレッドをプールしてはいけません。使い捨て前提の設計なので、プールすると本来の利点が消えます。CPUを使い続ける処理には効きません。効くのは待ち時間が長い処理なので、計算主体の処理に使っても速くならないんですよね。そしてThreadLocalとの相性です。仮想スレッドは大量に作られるので、それぞれがThreadLocalを持つとメモリを圧迫します。
Java 25 ── 現時点の最新LTS
2025年9月リリース。21以降の積み重ねを取り込んだバージョンですね。
入ったもの。Scoped Values の正式化。コンパクトなソースファイルとインスタンスmainメソッド。AOTの改善。コンパクトなオブジェクトヘッダ。そしてStable Values(Preview)。Structured Concurrencyなど、まだPreviewのものもあるので、本番投入の判断は分けて考えたいところです。
コンパクトなオブジェクトヘッダは25で正式な機能になりましたが、25では既定で有効ではなく、使うなら明示的な指定が要ります。これがJava 27で既定になりました(後述)。
Scoped Valuesという選択肢が増えました。リクエストのコンテキストのような不変のデータを、スコープの中で受け渡す用途に向いた仕組みです。不変で、スコープを抜けると自動で破棄されるので、仮想スレッドのように大量に作られる環境でもコストが低いんですよね。ただし「ThreadLocalの後継だから全部置き換える」という話ではありません。ThreadLocalにはスレッドごとの可変な状態を持つ用途もあります。思想が違うので、用途で選ぶものかなと思います。
学習用の書き方も入りました。
void main() {
System.out.println("Hello");
}
クラス宣言もstaticも要りません。これは従来のmainメソッドとは別の、新しいエントリーポイントの書き方ですね。あわせて、基本的なコンソール入出力のための仕組みも入っています。初学者が最初に書くコードの定型が減ったという意味では、教える側にとっても大きい変化かなと思います。
サポート期間。Oracle JDKの場合、Java 25は2030年9月までのPremier Support、2033年9月までのExtended Supportが予定されています。なおJavaはOracle JDKだけではありません。TemurinやCorretto、Libericaなど、ディストリビューションごとにサポート方針が違うので、自分たちが使っているものの条件を確認するのが確実です。
Java 26・27 ── 最新のフィーチャーリリース
どちらもLTSではありません。基本はLTSを土台に、という判断が定石ですが、次のLTS(29)に何が入ってくるかは、ここを見ると分かります。
Java 26(2026年3月)。どのGCでも使えるAOTのオブジェクトキャッシュ。HTTPクライアントのHTTP/3対応(既定はHTTP/2のままで、使うなら明示指定)。G1 GCの改善。Applet APIの削除。目玉はAOTのオブジェクトキャッシュで、起動時と暖機時の時間を短縮するためのもの。コンテナやサーバーレスでは効いてくる部分ですね。
Java 27(2026年9月15日)。コードを変えずに挙動が変わるものが2つあります。コンパクトオブジェクトヘッダ(12バイト→8バイト)が既定になり、ヒープ全体で数%〜十数%の削減が何もせずに手に入ること。そしてG1が全環境で既定のGCに統一されたこと。ほかに、TLS 1.3向けのポスト量子暗号ハイブリッド鍵交換、構造化並行性の7回目のプレビュー。値クラス(Project Valhalla)はその先のJDK 28でプレビュー予定です。
Java 27の中身は、Javaの真髄で「ほぉー」となったものだけ、8つ集めました で詳しく書いています。
早見表
| バージョン | リリース | 位置づけ | 代表的な機能 | この世代の心得 |
|---|---|---|---|---|
| 8 | 2014年 | LTS。いまも現役 | ラムダ、Stream、Optional、java.time | ループ内の文字列連結、parallelStream、ボクシング |
| 11 | 2018年 | LTS | var(10)、HTTPクライアント、Stringの便利メソッド | varの乱用、削除されたAPI |
| 17 | 2021年 | LTS。現場の主力 | switch式、テキストブロック、record、sealed | recordの浅い不変性、内部APIの制限 |
| 21 | 2023年 | LTS。現場の主力 | 仮想スレッド、recordパターン、世代別ZGC | synchronizedのピン留め(24で解消)、プール禁止 |
| 25 | 2025年9月 | 最新LTS | Scoped Values、インスタンスmain、AOT改善 | ヘッダ圧縮は明示指定、Previewの扱い |
| 26 | 2026年3月 | フィーチャー | AOTオブジェクトキャッシュ、HTTP/3 | 短い更新サイクル前提 |
| 27 | 2026年9月 | フィーチャー | ヘッダ圧縮とG1が既定、PQC鍵交換 | 同上 |
移行を考えるなら、ここは押さえたいです
Oracle JDK 21の無償アップデート。Oracle JDK 21は、無償で使える利用条件(NFTC)でのアップデート提供が2026年9月までとされていて、本記事の時点でその期限を迎えています。以降は別のライセンス条件に移行する見込みですね。ここ、誤解しやすいのですが、「Java 21というバージョン自体が有料になる」という話ではありません。Oracle OpenJDKのビルドもありますし、他のディストリビューションにもそれぞれのライセンスとサポートがあります。なので自分たちがどのJDKを使っているかの確認から始めるのが確実です。
進め方の順番。先に、既存のコードを新しいバージョンでそのまま安定させる。そのあとで、仮想スレッドなどの新機能を機能単位で入れていく。この2つを同時にやると、問題が起きたときに原因の切り分けができなくなるんですよね。工程を分けるのが安全かなと思います。
確認する対象。依存ライブラリの対応状況。削除されたAPI。JVMのオプション。この3つは必ず見ておきたいところです。
用途別に、どれを選ぶか
新規開発なら ── Java 25が有力です。長いサポートと、仮想スレッド周りの改良が揃っています。ただし社内標準やフレームワークの対応状況によっては、21を選ぶ合理性もありますね。
既存がJava 17なら ── 25へ直接という判断も十分現実的です。ただし大規模なシステムだと、17→21→25と段階的に検証する方が原因の切り分けがしやすい場面もあります。
既存がJava 21なら ── 仮想スレッドを本格的に使うなら25の価値が高いです。ピン留めの解消とScoped Valuesが揃うので。
既存がJava 8や11なら ── 最終的な移行先を先に決めて、必要なら17を中間の検証ポイントにする形かなと。「17に上げてから25」が必須というわけではないんですよね。そして、移行しない判断にも合理性があります。動き続けることが価値のシステムなら、8の心得を押さえて守り続けるのも立派な仕事です。
よくいただくご質問
Q. 最新版を追い続けるべきですか?
A. LTSを土台にするのが定石かなと思います。フィーチャーリリースは、新機能の検証用と考えるのが現実的ですよね。
Q. 仮想スレッド、いま入れるべきですか?
A. I/O待ちが多い処理なら効きます。ただしJava 23以前だとピン留めの問題があるので、バージョンとセットで判断したいところです。
Q. recordはどこまで使っていいですか?
A. 値の入れ物としては優秀です。ただし浅い不変性までなので、中に可変なものを入れるときは意識が要りますね。
Q. 未経験からでも、バージョンの違いは分かるようになりますか?
A. なります。むしろ「なぜこの書き方が増えたのか」を追うと、言語の考え方が見えてくるんですよね。
バージョンは、書き方の前提そのものです
同じJavaでも、バージョンが違えば書けることが変わります。そして今日書いたように、同じコードでも速度が変わることすらあるんですよね。仮想スレッドとsynchronizedの組み合わせが、まさにそれでした。
だから「Javaを書ける」だけでなく、いまどのバージョンで、何が使えて、何に気をつけるかまで含めて把握しておくと強いのかなと思います。8を守る人も、25を試す人も、同じ30年の積み重ねの上にいます。
みなさんの現場では、いまどのバージョンが動いていますか。移行の予定や、踏んだ落とし穴もあれば、ぜひ教えてください。
参考:OpenJDK JDK 27(2026年9月15日GA)/Oracle Java SE Support Roadmap/各ディストリビューション(Temurin・Corretto・Liberica)のサポート方針(いずれも2026年9月26日確認)
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。