Java 言語およびランタイム プラットフォーム Java 17 の長期サポート (LTS) バージョンは、2021 年 9 月 14 日にリリースされました。Java 17 の新機能と、アップグレードする必要があるかどうかを学びましょう。
多くのアプリケーションは、Java の以前の LTS バージョン (Java 11 および Java 8) を含む、古いバージョンの Java を使用しています。
企業はなぜ最新の Java バージョンにアップグレードする必要があるのでしょうか? Java 17 へのアップグレードには、主に JVM 内の新機能を最大限に活用するために労力が必要です。
多くの企業は、Docker と Docker イメージを使用して、最小限の労力と時間で簡単に Java 17 に切り替えています。開発者は、継続的インテグレーション/デプロイ (CI/CD) パイプラインを定義し、すべてを Docker イメージで実行できます。古い Java バージョンを使用している他のチームは古い Docker イメージを利用できるため、これは影響しません。

JAVA 17 の機能
macOS および AArch64 のサポート
このバージョンに追加された重要な JVM 機能の 1 つは、JEP 391 を使用した AArch64 アーキテクチャでの macOS のサポートの強化です。これは、Apple が昨年自社のコンピュータとともにリリースした最新のプロセッサ シリーズ (M1) をサポートします。
一部のベンダーはこのアーキテクチャをサポートするバージョンの JDK をリリースし、さらに Java 8 からサポートを戻しているため、これらのプラットフォームのユーザーにとっては必ずしも大きな問題ではありません。ただし、将来のメンテナンスとサポートを確実にするためには、公式の承認シールが不可欠です。プラットフォーム。比較すると、Linux/AArch64 プラットフォームのサポートは Java 9 と Java 16 の Windows/AArch64 に追加されました。
シールドされたクラス
Sealed Classes は Java 17 で導入された機能です。Sealed Classes 機能は試用段階を終了し、Java 17 の公式プラットフォームおよび言語になりました。これにより、開発者は、型が持つことができる許容されるサブタイプを指定でき、他者が意図しない方法でそれを拡張または実装することを防止します。
シールされたクラスでは、シールされていない型を許可されていないサブタイプに変換しようとすると、コンパイラがコンパイル時にエラーを生成することもできます。 Java 17 では、OpenGL の代わりに Apple Metal API を使用して macOS 上で実行される AWT/Swing アプリ用の新しいレンダリング パイプラインも導入されています。 API が改良され、乱数を生成する機能が強化されました。

Java 17 の変更、削除、制限事項
Java 17 では、いくつかの変更、削除、および新しい制限も加えられています。
JDK内部のカプセル化
変更の 1 つは、JDK Internals のカプセル化プロセスの終了です。これが初めて導入されたのは Java 9 内で、ユーザーが内部 API の使用に関する通常の制限を回避するためにリフレクションなどを使用しようとすると、実行時に警告が表示されました。この動作を規制するために、コマンドライン引数も追加されました。
Java 9 以降、最も一般的に使用されるタスクを実行するための統一された方法を提供するために、さまざまな API が作成されました。ユーザーはこれらの API を内部で利用することになります。 Java 16 では、デフォルトが警告からアクセスの無効化、例外のスローに変更されました。ただし、コマンドライン引数を使用して動作を変更します。
Java 17 では、コマンドライン引数が削除され、この制限を無効にすることができます。これは、これらの内部 API へのすべての非承認アクセスが保護されることを意味します。
常に厳密な浮動小数点セマンティクス
追加の「削除」は、Always-Strict Floating Point セマンティクスの再導入として説明できます。 Java 1.2 では、Java の浮動小数点セマンティクスのデフォルトに変更が導入され、JVM が浮動小数点計算のわずかな精度を犠牲にしてパフォーマンスを向上できるようになりました。厳密なセマンティクスを使用する必要があるクラスとメソッドでは、
strictfp
キーワードが追加されました。それ以来、さまざまな種類の命令セットが CPU に導入され、不必要なコストをかけずに厳密な浮動小数点セマンティクスが使用できるようになりました。デフォルトまたは厳密なセマンティクスを実装する必要はなくなりました。
Java 17 では、以前のデフォルトのセマンティクスが削除され、すべての浮動小数点演算が厳密に実行されます。
strictfp
用語はまだ存在します。ただし、効果はなく、コンパイル時に警告が発生します。
Ahead-of-Time (AOT) コンパイル
Java 9 では、Graal コンパイラを利用する実験的な機能として AOT (Ahead-of-Time) コンパイルが導入され、JIT コードは Java を使用して記述されました。 Java 10 では、JVMCI インターフェースを組み込むことにより、Graal コンパイラーを OpenJDK の JIT コンパイラーとして使用できるようになりました。リリースされて以来、大幅な改良が加えられました。 Graal コンパイラは目覚ましい進歩を遂げており、その JVM は GraalVM という名前で提供されています。
RMIのアクティベーション
RMI アクティベーションは、Java 8 から削除された後、 JEP 407 で削除され、最終的に非推奨となり、Java 15 内で削除の要件としてマークされました。 RMI アクティベーションは、RMI を使用して分散オブジェクトをオンデマンド リソースで有効にする方法を提供しました。ただし、使用頻度は最小限であり、現在ではより優れた代替手段が利用可能です。 RMI の残りの部分は、アクティベーション部分の削除による影響を受けません。
アプレット API の削除
アプレット API は、最終的に JEP 398 によって削除対象として指定されましたが、最初は Java 9 内で削除されました。アプレット API は、Java AWT/Swing コントロールをブラウザ内の Web ページに統合する方法を提供しました。ただし、最新のブラウザーはこれをサポートできません。つまり、過去 10 年ほどにわたってアプレットには基本的にアクセスできなくなりました。
保安管理者
最も重要な非推奨は、セキュリティ マネージャー ( JEP 411 ) です。 Security Manager は Java 1.0 からしばらく使用されてきました。これは、ネットワーク、ファイル、その他のネットワーク リソースへのアクセスを制限するなど、Java がマシン上でローカルに実行できることを制限するように設計されています。また、リフレクションと特定の API をブロックすることで、信頼されていないコードをサンドボックス化しようとします。
Java 12 でセキュリティ マネージャーが終了しました。実行時にセキュリティ マネージャーの使用をブロックするコマンドライン引数が追加されました。 Java 17 で行われた変更は、コマンド ラインから、または実行時に動的にセキュリティ マネージャーを設定しようとすると、JVM で実行時警告が生成されることを意味します。

インキュベーターとプレビューの機能
Java 17 が長期サポートされるバージョンに昇格したことを考慮すると、Java 17 にプレビュー機能やインキュベーター機能が搭載されるかどうか疑問に思う人も少なくありません。 Java 17 には 2 つのインキュベーター モジュールとプレビュー機能があります。
ベクターAPI
Vector API ( JEP 414 ) は現在、インキュベーターの第 2 フェーズにあります。 API を使用すると、開発者はベクトル計算を定義でき、JIT コンパイラーは、JVM が実行される CPU アーキテクチャによってサポートされる適切なベクトル命令 (たとえば、SSE または AVX 命令セットを使用) に変換します。
以前は、開発者はスカラー関数を使用するか、プラットフォームに固有のネイティブ ライブラリを構築する必要がありました。 Java で Vector API を実装すると、以前のバージョンでは複雑だったシームレスなフォールバック メカニズムも提供されます。
Vector API の標準化により、JDK 内のクラスで Vector API を使用できるようになります。 Java 配列の missmatch() メソッドは、代わりに Java 上で実行されるように変更でき、JVM 内で複数のプラットフォーム固有の実装を維持および作成する必要がなくなります。
外部関数とメモリ API
追加のインキュベーター機能は、Foreign Function & Memory API ( JEP 412 ) と呼ばれます。これは、Java 16 の他の 2 つのインキュベーター モジュール、Foreign Linker API ( JEP 389 ) とForeign-Memory API ( JEP 393 ) の進化および統合です。どちらも、Java で記述された静的型付けプログラミングを使用して、ネイティブ メモリとコードへのアクセスを提供します。
スイッチのパターンマッチング
Java 17 に含まれる言語プレビューの最後の機能は、Pattern Matching for Switch ( JEP 406 ) が含まれていることです。この言語機能は、Java 16 で標準となったパターン マッチング ( JEP 394 ) で使用される構文と同様に、switch 式とステートメントをタイプに応じて拡張します。
以前は、オブジェクトの動的な性質に基づいてさまざまなアクションを実行したい場合は、次のようなチェックのインスタンスを使用して if-else チェーンを構築する必要がありました。
String type(Object o) {
if (o instanceof List) {
return "A List of things.";
}
else if (o instanceof Map) {
return "A Map! It has keys and values.";
}
else if (o instanceof String) {
return "This is a string.";
}
else {
return "This is something else.";
}
}
switch 式とスイッチの新しいパターン マッチング機能を組み合わせることで、プロセスを次のようなものに減らすことができます。
String type(Object o) {
return switch (o) {
case List l -> "A List of things.";
case Map m -> "A Map! It has keys and values.";
case String s -> "This is a string.";
default -> "This is something else.";
};
}
お気づきかと思いますが、チェックの過程で変数の宣言が行われています。 Pattern の他の変数と同様に、インスタンスの一致は、このオブジェクトが型チェックおよびキャストされ、現在の領域内の変数から使用できることを示します。
プレビュー機能は、パターン マッチングへの新たな一歩です。次のステップは、配列とレコードを分解する機能を組み込むことです。

Java 17 にアップグレードする必要がありますか?
はい、常に最新バージョンにアップグレードする必要がありますが、初日からすぐにアップグレードする必要はありません。使用しているソフトウェアとライブラリは Java 17 との互換性を含めるように更新されていない可能性があるため、更新が完了するまでしばらく待つ必要がある場合があります。
Java 8 や Java 11 などの LTS バージョンの Java に行き詰まっている場合は、言語内および JVM 自体内に Java 17 へのアップグレードを必要とする多数のオプションがあります。これは長期メンテナンス リリースであるため、最終的には実稼働環境も Java 17 に更新される可能性が高くなります。
まったく新しいプロジェクトを開始している場合、またはプロジェクトを Java 17 に対応できるように準備している途中の場合は、移行コストが削減されるため、早めに Java 17 に切り替えることがおそらく最も効率的な選択です。これにより、プロジェクトに取り組んでいる開発者は、最新の機能と運用面をすべて利用できるようになります。
Java 上で実行されるコンテナーのサポートの改善や、新しい低遅延ガベージ コレクターの実装など、過去数年間に行われた多くの改善を活用できます。
