Java 17の新機能
公開: 2021-10-05Java言語およびランタイムプラットフォームJava17のロングタームサポート(LTS)バージョンが2021年9月14日にリリースされました。Java17の新機能と、アップグレードする必要があるかどうかを学びましょう。
多くのアプリケーションは、以前のLTSバージョンのJava(Java11およびJava8)を含む古いバージョンのJavaを使用します。
なぜ企業は最新のJavaバージョンにアップグレードする必要があるのですか? Java 17へのアップグレードには、主にJVM内の新機能を最大限に活用するための努力が必要です。
多くの企業は、DockerおよびDockerイメージを使用して、最小限の労力と時間でJava17に簡単に切り替えることができます。 開発者は、継続的インテグレーション/デプロイメント(CI / CD)パイプラインを定義し、すべてをDockerイメージで実行できます。 古いDockerイメージを利用できるため、古いバージョンのJavaを使用している他のチームには影響しません。
JAVA17の機能
macOSとAArch64のサポート
このバージョンに追加された重要なJVM機能の1つは、JEP 391を使用したAArch64アーキテクチャでのmacOSのサポートの強化です。これは、Appleが昨年コンピューターでリリースした最新の一連のプロセッサー(M1)をサポートします。
一部のベンダーは、このアーキテクチャをサポートし、Java 8からのサポートを返すバージョンのJDKをリリースしているため、これらのプラットフォームのユーザーにとって必ずしも大したことではありません。ただし、将来のメンテナンスとサポートを確実にするには、正式な承認シールが不可欠です。プラットフォーム。 これに対して、Linux / AArch64プラットフォームのサポートがJava9およびJava16のWindows / AArch64に追加されました。
封印されたクラス
封印されたクラスは、Java 17で導入された機能です。封印されたクラス機能は、トライアルフェーズを終了し、Java 17の公式プラットフォームおよび言語になりました。これにより、開発者は、タイプが持つことができる許容サブタイプを指定できます。他の人が意図しない方法でそれを拡張または実装することを防ぎます。
封印されたクラスを使用すると、封印されていない型を許可されていないサブ型に変換しようとしたときに、コンパイラがコンパイル時にエラーを生成することもできます。 Java 17は、OpenGLの代わりにApple MetalAPIを使用してmacOS上で実行されるAWT / Swingアプリ用の新しいレンダリングパイプラインももたらします。 APIが改善され、乱数を生成する機能が強化されています。
Java 17での変更、削除、および制限
Java 17には、いくつかの変更、削除、および新しい制限もあります。
JDK内部のカプセル化
1つの変更は、JDKInternalsのカプセル化プロセスの結論です。 これが最初に導入されたのはJava9内であり、ユーザーがリフレクションなどを使用して内部APIの使用に関する通常の制限を回避しようとすると、実行時に警告が表示されます。 この動作を調整するために、コマンドライン引数も追加されました。
Java 9から、最も一般的に使用されるタスクを実行するための統一された方法を提供するために、さまざまなAPIが作成されました。 ユーザーはこれらのAPIを内部で利用します。 Java 16では、デフォルトが警告からアクセスの無効化、例外のスローに変更されました。 ただし、コマンドライン引数を使用して動作を変更します。
Java 17では、コマンドライン引数が削除され、この制限を無効にすることができます。 これは、これらの内部APIへの許可されていないすべてのアクセスが保護されることを意味します。
常に厳密な浮動小数点セマンティクス
追加の「削除」は、Always-Strict FloatingPointセマンティクスの再導入として説明できます。 Java 1.2では、Javaの浮動小数点セマンティクスのデフォルトに変更が加えられ、JVMが浮動小数点計算でわずかな精度でトレードできるようになり、パフォーマンスが向上しました。 厳密なセマンティクスを使用する必要があるクラスとメソッドでは、 strictfpキーワードが追加されました。 それ以来、さまざまな命令セットタイプがCPUに導入され、厳密な浮動小数点セマンティクスを不要なコストなしで使用できるようになりました。 デフォルトまたは厳密なセマンティクスを実装する必要がなくなりました。
Java 17は、以前のデフォルトのセマンティクスを削除し、すべての浮動小数点演算が厳密に実行されます。 strictfpという用語はまだ存在しています。 ただし、効果はなく、コンパイル時に警告が発生します。
Ahead-of-Time(AOT)コンパイル
Java 9は、Graalコンパイラーを利用する実験的な機能として事前(AOT)コンパイルを導入し、JITコードはJavaを使用して記述されました。 Java 10は、JVMCIインターフェースを組み込むことにより、GraalコンパイラーをOpenJDKのJITコンパイラーとして使用できるようにしました。 リリースされて以来、大幅な改善が行われています。 Graalコンパイラは驚異的な進歩を遂げており、GraalVMという名前でJVMを使用しています。
RMIアクティベーション
RMIアクティベーションは、Java8からの削除後にJEP407で削除され、最終的に非推奨になり、Java 15内での削除の要件としてマークされました。RMIアクティベーションは、RMIを使用して分散オブジェクトのオンデマンドリソースを有効にする方法を提供しました。 ただし、使用量は最小限であり、現在はより良い代替手段が利用可能です。 RMIの残りの部分は、アクティベーション部分の削除による影響を受けません。
アプレットAPIの削除
Applet APIは、最終的にJEP 398によって削除対象として指定され、最初はJava9内で削除されました。AppletAPIは、Java AWT / Swingコントロールをブラウザ内のWebページに統合する方法を提供しました。 ただし、最新のブラウザではこれをサポートできません。つまり、過去10年ほどの間、アプレットには基本的にアクセスできませんでした。

保安管理者
最も重大な非推奨は、セキュリティマネージャ(JEP 411)です。 Security Managerは、Java1.0からしばらく使用されています。 これは、ネットワーク、ファイル、およびその他のネットワークリソースへのアクセスを制限するなど、Javaがマシン上でローカルに実行できることを制限するように設計されています。 また、リフレクションと特定のAPIをブロックすることにより、信頼されていないコードをサンドボックス化しようとします。
SecurityManagerの終了はJava12で開始されました。実行時にSecurityManagerの使用をブロックするコマンドライン引数が追加されました。 Java 17で行われた変更は、コマンドラインからまたは実行時に動的にセキュリティマネージャを設定しようとすると、JVMで実行時警告が生成されることを意味します。
インキュベーターとプレビュー機能
多くの人が、Java 17が長期的にサポートされるバージョンに昇格したことを考えると、Java17にプレビュー機能とインキュベーター機能があるかどうか疑問に思いました。 Java 17には、2つのインキュベーターモジュールとプレビュー機能があります。
ベクターAPI
Vector API(JEP 414)は、現在インキュベーターの第2フェーズにあります。 APIを使用すると、開発者は、JITコンパイラがJVMが実行されるCPUアーキテクチャでサポートされる適切なベクトル命令に変換するベクトル計算を定義できます(たとえば、SSEまたはAVX命令セットの命令セットを使用)。
以前は、開発者はスカラー関数を使用するか、プラットフォームに固有のネイティブライブラリを構築する必要がありました。 JavaでVectorAPIを実装すると、以前のバージョンでは複雑だったシームレスなフォールバックメカニズムも提供されます。
Vector APIの標準化により、JDK内のクラスで使用できるようになります。 Java配列のmismatch()メソッドを変更して、代わりにJavaで実行できるようにすることで、JVM内で複数のプラットフォーム固有の実装を維持および作成する必要がなくなります。
外部関数とメモリAPI
追加のインキュベーター機能は、Foreign Function&Memory API(JEP 412)と呼ばれます。 これは、Java 16の他の2つのインキュベーターモジュールであるForeignLinker API(JEP 389)とForeign-Memory API(JEP 393)の進化と統合です。 どちらも、Javaで記述された静的型付けプログラミングを使用して、ネイティブメモリとコードへのアクセスを提供します。
スイッチのパターンマッチング
Java 17に含まれる言語プレビューの最後の機能は、Switchのパターンマッチング(JEP 406)が含まれていることです。 この言語機能は、Java 16で標準となったパターンマッチング(JEP 394)で使用される構文と同様に、タイプに応じてスイッチ式とステートメントを拡張します。
以前は、オブジェクトの動的な性質に基づいてさまざまなアクションを実行する場合は、次のようなチェックのインスタンスを使用して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."; } }スイッチ式とスイッチの新しいパターンマッチング機能を組み合わせることで、プロセスを次のようなものに減らすことができます。
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の他の変数と同様に、インスタンスの一致は、このオブジェクトがタイプチェックされてキャストされ、現在の領域内の変数から利用できることを示します。
プレビュー機能は、パターンマッチングに向けたもう1つのステップです。 次のステップは、配列とレコードを分解する機能を含めることです。
Java 17にアップグレードする必要がありますか?
はい、常に最新バージョンにアップグレードする必要がありますが、初日からではありません。 使用しているソフトウェアとライブラリは、Java 17との互換性を含むように更新されていない可能性があるため、完了するまでしばらく待つ必要がある場合があります。
Java8やJava11などのLTSバージョンのJavaを使い続けている場合は、言語内およびJVM自体に、Java 17へのアップグレードを必要とする多数のオプションがあります。これは長期的なメンテナンスリリースであるため、次のようなものがあります。実稼働環境も最終的にJava17に更新される可能性が高くなります。
まったく新しいプロジェクトを開始する場合、またはプロジェクトをJava 17に対応させる準備をしている場合は、移動のコストを削減できるため、Java17への切り替えを後で行うのではなく早く行うのがおそらく最も効率的な選択です。 これにより、プロジェクトに取り組んでいる開発者は、すべての最新機能と運用面を利用することもできます。
Javaで実行されるコンテナのサポートの改善や、新しい低レイテンシのガベージコレクタの実装など、過去数年間に発生した多くの改善を利用できます。
