7 JDK 8から後続のJDKリリースへの移行

JDK 8と後続のJDKリリースとの間では、重要な変更が行われました。

新しいJava SEがリリースされると必ず、以前のリリースとのバイナリ、ソース、および動作上の非互換が発生します。JDK 9以降で発生したJava SEプラットフォームのモジュール化には多くのメリットがありましたが、同時に多くの変更も伴いました。公式のJava SEプラットフォームAPIおよびサポートされているJDK固有のAPIのみを使用するコードは、変更なしでそのまま動作します。JDK内部APIを使用するコードは引き続き動作しますが、サポート対象のAPIを使用するように移行する必要があります。

アクセス不可となった、削除された、またはデフォルト動作が変更されたAPIもあります。アプリケーションのコンパイルまたは実行時に問題が発生する可能性があります。削除されたツールとコンポーネントおよびセキュリティ・アップデートを参照してください。

次の各項では、JDK 8アプリケーションを後続のJDKリリースに移行する際に注意する必要があるJDKパッケージの変更点について説明します。

アプリケーション実行の際に遭遇する可能性のある変更のリストを確認します。

アプリケーションが最新バージョンのJDKで正常に動作するようになったら、「次のステップ」を確認し、今後のリリースにおいて問題が発生するのを回避するのに役立てます。

JDK内の強力なカプセル化

一部のツールやライブラリでは、リフレクションを使用して内部使用のみを目的としたJDKの部分にアクセスします。このようなリフレクションの使用は、JDKのセキュリティおよび保守性に悪影響を及ぼします。移行を支援するために、JDK 9からJDK 16まではこのリフレクションの継続を許可していましたが、不正なリフレクション・アクセスについては警告が発行されていました。ただし、JDK 17は強力にカプセル化されているため、このリフレクションはデフォルトでは許可されなくなりました。java.* APIの非パブリック・フィールドおよびメソッドにアクセスするコードは、InaccessibleObjectExceptionをスローします。

sun.miscおよびsun.reflectパッケージは、JDK 17を含むすべてのJDKリリースのツールおよびライブラリによるリフレクションに使用できます。

java起動ツール・オプション--illegal-accessにより、JDK 9からJDK 16のJDK内部へのリフレクションが可能になりました。次のパラメータを指定できます:

  • --illegal-access=permit: クラス・パス上のコードは、JDK 8に存在していたjava.*パッケージの内部をリフレクトできます。このような要素に対して初めてリフレクション・アクセス操作を行うと、警告が発行されますが、それ以降、警告は発行されません。
  • --illegal-access=warn: 不正なリフレクション・アクセス操作ごとに警告メッセージが発行されます。
  • --illegal-access=debug: 不正なリフレクション・アクセス操作ごとに警告メッセージとスタック・トレースの両方が表示されます。
  • --illegal-access=deny: 不正なリフレクション・アクセス操作をすべて無効にしますが、--add-opensなどの他のコマンドライン・オプションによって有効にされている操作は除きます。

多くのツールおよびライブラリが更新され、JDK内部に依存せず、かわりにJDK 8から17の間で導入された標準のJava APIを使用するようになりました。つまり、--illegal-access起動ツール・オプションはJDK 17では廃止されています。JDK 17でこの起動ツール・オプションを使用する場合、permitwarndebugまたはdenyのいずれを使用しても、警告メッセージを発行する以外の効果はありません。

新しいバージョンのツールおよびライブラリを取得またはデプロイできない場合は、古いバージョンのツールおよびライブラリの特定の内部APIへのアクセス権を付与できる2つのコマンドライン・オプションがあります:

  • --add-exports: 強力にカプセル化された内部APIを使用する必要のある古いツールまたはライブラリがある場合は、--add-exportsランタイム・オプションを使用します。コンパイル時に--add-exportsを使用して内部APIにアクセスすることもできます。
  • --add-opens: リフレクションによってjava.* APIの非パブリック・フィールドおよびメソッドにアクセスする必要のある古いツールまたはライブラリがある場合は、--add-opensオプションを使用します。

JEP 403: デフォルトでのJDK内部の強力なカプセル化に関する項を参照してください。

--add-exports

強力にカプセル化された内部APIを使用する必要のある古いツールまたはライブラリがある場合は、--add-exportsランタイム・オプションを使用します。コンパイル時に--add-exportsを使用して内部APIにアクセスすることもできます。

--add-exportsオプションの構文は次のとおりです。
--add-exports <source-module>/<package>=<target-module>(,<target-module>)*
ここで、<source-module>および<target-module>はモジュール名、<package>はパッケージの名前です。

--add-exportsオプションでは、ターゲット・モジュールがソース・モジュールを読み取る場合に、ターゲット・モジュール内のコードがソース・モジュールの名前付きパッケージ内のタイプにアクセスすることを許可します。

特殊なケースとして、<target-module>ALL-UNNAMEDの場合、ソース・パッケージが名前のないすべてのモジュールに、それが最初から存在するか後から作成されたかにかかわらずエクスポートされます。次に例を示します:
--add-exports java.management/sun.management=ALL-UNNAMED
この例では、名前のないすべてのモジュールのコード(クラス・パスにあるコード)がjava.management/sun.managementのpublicタイプのpublicメンバーにアクセスできるようにします。

ノート:

クラス・パスのコードで、リフレクションAPI (setAccessible(true))を使用して、java.* APIの非パブリック・フィールドおよびメソッドへのアクセスを試みると、コードは失敗します。JDK 17では、これはデフォルトでは許可されません。ただし、--add-opensオプションを使用するとこれを許可できます。詳細は、「--add-opens」の項を参照してください。
クラス・パスで実行されるアプリケーションoldAppが、java.managementモジュールのエクスポートされていないcom.sun.jmx.remote.internalパッケージを使用する必要がある場合、必要なアクセス権を次のように付与できます。
--add-exports java.management/com.sun.jmx.remote.internal=ALL-UNNAMED
Add-Exports JARファイル・マニフェスト属性を使用することもできます:
Add-Exports:java.management/sun.management

--add-exportsオプションは慎重に使用してください。これを使用すれば、ライブラリ・モジュールの内部APIに、またはJDKそのものの内部APIであってもアクセスできますが、これは自己責任になります。その内部APIが変更または削除されると、ライブラリやアプリケーションは失敗します。

JEP 261: モジュール・システムに関する項を参照してください。

--add-opens

一部のツールおよびライブラリは、リフレクションAPI (setAccessible(true))を使用して、java.* APIの非パブリック・フィールドおよびメソッドへのアクセスを試みます。これは、JDK 17ではデフォルトで使用できなくなりましたが、コマンドラインで--add-opensオプションを使用して、特定のツールおよびライブラリに対して有効にできます。

--add-opensオプションの構文は次のとおりです。
--add-opens <module>/<package>=<target-module>(,<target-module>)*
このオプションでは、モジュール宣言に関係なく、<module><package><target-module>にオープンにすることを許可します。
特殊なケースとして、<target-module>ALL-UNNAMEDの場合、ソース・パッケージが名前のないすべてのモジュールに、それが最初から存在するか後から作成されたかにかかわらずエクスポートされます。次に例を示します:
--add-opens java.management/sun.management=ALL-UNNAMED
この例では、クラス・パスにあるすべてのコードがjava.management/sun.managementパッケージのpublicタイプの非publicメンバーにアクセスできるようにします。

ノート:

Java Web StartのJNLPファイルでは、--add-opensとその値の間に等号を含める必要があります。
<j2se version="10" java-vm-args="--add-opens=<module>/<package>=ALL-UNNAMED"  />

--add-opensとその値の間の等号記号は、コマンド・ラインのオプションです。

新しいバージョン文字列スキーム

JDK 10では、時間ベースの解放モデルへの対応を改善するために、JDK 9で導入されたバージョン文字列のスキームが少し変更されています。JDK 11以降ではJDK 10で導入されたバージョン文字列の書式が保持されます。

コードでメジャー、マイナー、セキュリティおよびパッチ更新を識別するのにバージョン文字列形式に依存している場合、更新が必要となる可能性があります。

新しいバージョン文字列の形式は次のとおりです。

$FEATURE.$INTERIM.$UPDATE.$PATCH

バージョン文字列を解析、検証および比較するための単純なJava APIが追加されました。java.lang.Runtime.Versionに関する項を参照してください。

Java Platform, Standard Editionインストレーション・ガイドバージョン文字列の書式を参照してください。

JDK 9で導入されたバージョン文字列に対する変更の詳細は、JEP 223: 新規バージョン文字列のスキームを参照してください。

JDK 10で導入されたバージョン文字列の変更の詳細は、JEP 322: 時間ベースのリリースのバージョニングを参照してください。

インストール済JDK/JREイメージに加えられた変更

JDKおよびJREに大きな変更が加えられています。

JDKおよびJREレイアウトの変更

JDKのインストール後にファイル・システムを参照するとわかるとおり、ディレクトリ・レイアウトがJDK 9より前のリリースとは異なっています。

JDK 11以降

JDK 11以降にはJREイメージがありません。『Java Platform, Standard Editionインストレーション・ガイド』JDKのインストール済ディレクトリの構造に関する項を参照してください。

JDK 9およびJDK 10

以前のリリースには2種類のランタイム・イメージがありました。1つはJREで、これはJava SE Platformの完全な実装、もう1つはJDKで、JRE全体がjre/ディレクトリに、開発ツールとライブラリとともに格納されていました。

JDK 9およびJDK 10では、JDKとJREは2種類のモジュラ・ランタイム・イメージで、次のディレクトリが含まれています。

  • bin: バイナリ実行可能ファイルが格納されます。

  • conf: 開発者、デプロイ実行者およびエンド・ユーザーによる編集を意図した、.properties.policyおよびその他のファイルが格納されます。これらのファイルは以前はlibディレクトリまたはそのサブディレクトリにありました。

  • lib: 動的にリンクされるライブラリおよびJDKの完全な内部実装が格納されます。

JDK 9およびJDK 10では、JDKとJREのダウンロードは引き続き分かれていますが、それぞれのディレクトリ構造は同じです。JDKイメージには、これまでJDKで提供されてきた追加のツールおよびライブラリが含まれています。jdk/jre/のラッパー・ディレクトリはなく、(javaコマンドなどの)バイナリは複製されません。

『JEP 220: Modular Run-Time Images』を参照してください。

新しいクラス・ローダー実装

JDK 9以降のリリースでは1.2リリースから存在するクラス・ローダー階層が引き続き保持されます。ただし、モジュール・システムの実装のために次の変更が加えられました。

  • アプリケーション・クラス・ローダーはURLClassLoaderのインスタンスではなくなり、内部クラスのインスタンスになります。これは、Java SEモジュールでもJDKモジュールでもないモジュールのクラスのデフォルト・ローダーです。

  • 拡張クラス・ローダーという名前がプラットフォーム・クラス・ローダーという名前に変更されました。Java SEプラットフォームのすべてのクラスは、プラットフォーム・クラス・ローダーにより参照可能となることが保証されます。

    クラスがプラットフォーム・クラス・ローダーにより参照可能であるからというだけで、クラスが実際にプラットフォーム・クラス・ローダーにより定義されているということにはなりません。Java SEプラットフォームの一部のクラスはプラットフォーム・クラス・ローダーにより定義されているのに対し、あるものはブートストラップ・クラス・ローダーにより定義されています。アプリケーションは、どのクラス・ローダーでどのプラットフォーム・クラスが定義されているかに依存しないようにしてください。

    JDK 9で実装されたこの変更は、親クラス・ローダーとしてnull (つまり、ブートストラップ・クラス・ローダー)が設定されたクラス・ローダーを作成し、親からすべてのプラットフォーム・クラスが参照可能であることを前提とするコードに影響する可能性があります。そのようなコードは、親としてプラットフォーム・クラス・ローダーを使用するように変更する必要があります(ClassLoader.getPlatformClassLoaderを参照してください)。

    プラットフォーム・クラス・ローダーはURLClassLoaderのインスタンスではなく、内部クラスのインスタンスです。

  • ブートストラップ・クラス・ローダーは引き続きJava仮想マシンに組み込まれており、ClassLoader APIにおいてnullで表されます。ここでは、java.baseといった、いくつかの重要なモジュールのクラスが定義されています。その結果、ここで定義されるクラスの数はJDK 8に比べてかなり少なくなり、-Xbootclasspath/aによりデプロイされるアプリケーションや親としてnullが設定されたクラス・ローダーを作成するアプリケーションは、前述のように変更が必要となる可能性があります。

rt.jarおよびtools.jarの削除

以前にlib/rt.jarlib/tools.jarlib/dt.jarおよびその他の各種内部JARファイルに格納されていたクラスおよびリソースのファイルは、libディレクトリ内の実装固有のファイルにさらに効率的な形式で格納されています。

rt.jarおよび同様のファイルの削除により、次のような問題が発生します。

  • JDK 9以降では、ClassLoader.getSystemResourceはJARファイルを指すURLは返しません(JARファイルがないため)。かわりに、ランタイム・イメージに格納されたモジュール、クラス、およびリソースの名前をそのイメージの内部構造や形式を公開することなく示す、jrt URLを返します。

    次に例を示します:

    ClassLoader.getSystemResource("java/lang/Class.class");

    JDK 8で実行すると、このメソッドは次の形式のJAR URLを返します。

    jar:file:/usr/local/jdk8/jre/lib/rt.jar!/java/lang/Class.class

    これにはラインタイム・イメージ内の実際のJARファイルの名前を示すファイルURLが含まれています。

    モジュラ・イメージにはJARファイルは含まれないため、この形式のURLは意味をなしません。JDK 9以降のリリースでは、このメソッドは次の値を戻します。
    jrt:/java.base/java/lang/Class.class
  • java.security.CodeSource APIおよびセキュリティ・ポリシー・ファイルでは、特定の権限が付与されるコード・ベースの場所を示すのにURLを使用します。Java Platform, Standard Editionセキュリティ開発者ガイドポリシー・ファイル構文に関する項を参照してください。特定の権限を必要とするランタイム・システムのコンポーネントは現在、conf/security/java.policyファイルにおいてファイルURLを使用して識別されます。

  • 旧バージョンのIDEやその他の開発ツールでは、ランタイム・イメージに格納されたクラス・ファイルおよびリソース・ファイルを列挙する機能、およびrt.jarファイルおよび同様のファイルをオープンして読み取ることによりそのコンテンツを直接読み取る機能が必要となります。これはモジュラ・イメージでは不可能です。

拡張機能メカニズムの削除

JDK 8以前では、拡張メカニズムにより、クラス・パスで明示的に指定しなくても、ランタイム環境において拡張クラスを検出してロードすることが可能でした。JDK 9以降では、拡張クラスを使用する必要がある場合、JARファイルがクラス・パスにあることを確認してください。

JDK 9およびJDK 10では、java.ext.dirsシステム・プロパティが設定されている場合、またはlib/extディレクトリが存在する場合、javacコンパイラおよびjava起動ツールは終了します。プラットフォーム固有のディレクトリをシステム規模でさらに確認するには、-XX:+CheckEndorsedAndExtDirsコマンドライン・オプションを指定します。これにより、このディレクトリが存在していてかつ空でない場合に同じ終了動作が発生します。拡張クラス・ローダーはJDK 9以降のリリースでも引き続き保持され、プラットフォーム・クラス・ローダーとして指定されています(getPlatformClassLoaderを参照。)ただし、JDK 11でこのオプションは廃止され、使用すると警告が発行されます。

次のエラーは、システムが拡張メカニズムを使用するよう構成されていることを示しています。

<JAVA_HOME>/lib/ext exists, extensions mechanism no longer supported; Use -classpath instead.
.Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

java.ext.dirsシステム・プロパティが設定されている場合も同様のエラーが表示されます。

このエラーを修正するには、ext/ディレクトリまたはjava.ext.dirsシステム・プロパティを削除します。

『JEP 220: Modular Run-Time Images』を参照してください。

推奨標準優先メカニズムの削除

java.endorsed.dirsシステム・プロパティおよびlib/endorsedディレクトリは存在しなくなりました。このいずれかが検出された場合、javacコンパイラおよびjava起動ツールは終了します。

JDK 9以降では、アップグレード可能なモジュールを使用するか、またはJARファイルをクラス・パスに指定します。

このメカニズムは、アプリケーション・サーバーがJDKで使用されるコンポーネントをオーバーライドできるよう意図するものでした。更新されるパッケージはJARファイルに配置され、それがどこにあるかはシステム・プロパティjava.endorsed.dirsによりJavaランタイム環境側で判断できるようになっていました。このプロパティが指定されていない場合、デフォルトとして$JAVA_HOME/lib/endorsedが使用されるようになっていました。

JDK 8では、-XX:+CheckEndorsedAndExtDirsコマンドライン引数を使用して、システム上のどこかにあるそのようなディレクトリをチェックできます。

JDK 9以降のリリースでは、java.endorsed.dirsシステム・プロパティが設定されている場合、またはlib/endorsedディレクトリが存在する場合、javacコンパイラおよびjava起動ツールは終了します。

次のエラーは、システムが標準の推奨オーバーライド・メカニズムを使用するよう構成されていることを示しています。

<JAVA_HOME>/lib/endorsed is not supported. Endorsed standards and standalone APIs
in modular form will be supported via the concept of upgradeable modules.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

java.endorsed.dirsシステム・プロパティが設定されている場合も同様のエラーが表示されます。

このエラーを修正するには、lib/endorsedディレクトリを削除するか、またはjava.endorsed.dirsシステム・プロパティを設定解除します。

『JEP 220: Modular Run-Time Images』を参照してください。

削除されたmacOS固有の機能

この項では、JDK 9以降で削除されたmacOS固有の機能について説明します。

プラットフォーム固有のデスクトップ機能

java.awt.Desktopクラスには、Apple固有のcom.apple.eawtおよびcom.apple.eioパッケージにあるAPIの代替が含まれています。新しいAPIはmacOS APIを置き換えるもので、プラットフォームに依存しません。

com.apple.eawtおよびcom.apple.eioパッケージのAPIはカプセル化されているため、JDK 9以降のリリースでこれらに対してコンパイルすることはできません。ただし、実行時にはアクセス可能であるため、古いバージョンにコンパイルされた既存のコードは引き続き動作します。最終的には、appleおよびcom.appleパッケージおよびそのサブパッケージの内部クラスを使用するライブラリやアプリケーションは新しいAPIへの移行が必要となります。

com.apple.concurrentおよびapple.applescriptパッケージは削除されており、代替はありません。

『JEP 272: Platform-Specific Desktop Features』を参照してください。

AppleScriptエンジンの削除

プラットフォーム固有のjavax.script実装であるAppleScriptエンジンはJDKで削除されており、代替はありません。

AppleScriptエンジンは、最近のリリースではほぼ使用できませんでした。JDK 7やJDK 8においてこの機能は、AppleバージョンのAppleScriptEngine.jarファイルがシステムにある場合にのみ動作していました。

Windowsレジストリ・キーの変更

Java 11以降のインストーラは、次のWindowsレジストリ・キーをJDKのインストール時に作成します。JDK 16の場合、インストーラによって次のWindowsレジストリ・キーが作成されます:

  • "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK"

  • "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\16"

JDKの2つのバージョンがインストールされている場合、2つの異なるWindowsレジストリ・キーが作成されます。たとえば、JDK 15.0.1をJDK 16とともにインストールする場合は、インストーラによって次のように別のWindowsレジストリ・キーが作成されます。

  • "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK"

  • "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\16"

  • "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\15.0.1"

デプロイメント

Javaデプロイメント・テクノロジはJDK 9で非推奨になり、JDK 11で削除されました。

事前インストールされたシステムJREに依存するのではなく、JDK 9で導入されたjlinkツールを使用して、専用のランタイムをパッケージ化してデプロイしてください。

起動時のJREバージョン選択の削除

JDK 9以降では、起動時に起動されるJREとは異なるバージョンのJREを要求する機能は削除されています。

近年のアプリケーションは通常、Java Web Start (JNLP)、ネイティブOSパッケージ化システムまたはアクティブ・インストーラを使用してデプロイされます。これらのテクノロジは、必要なJREを必要に応じてダウンロードおよび更新する、必要となるJREを管理する独自の方法を備えています。そのため、起動ツールの起動時JREバージョン選択は非推奨となりました。

以前のリリースでは、アプリケーションの起動時にどのJREバージョン(またはバージョンの範囲)を使用するかを指定できました。バージョンの選択は、コマンドライン・オプションまたはアプリケーションのJARファイルのマニフェスト・エントリで可能でした。

JDK 9以降では、java起動ツールが次のように変更されています。
  • コマンドラインで-version:オプションが指定されているとエラー・メッセージを出力して終了します。
  • JRE-Versionマニフェスト・エントリがJARファイルにあると、警告メッセージを出力して続行します。

『JEP 231: Remove Launch-Time JRE Version Selection』を参照してください。

シリアライズされたアプレットのサポートの削除

JDK 9以降では、アプレットをシリアライズ・オブジェクトとしてデプロイする機能はサポートされていません。近年の圧縮およびJVMのパフォーマンスでは、このようにアプレットをデプロイするメリットはありません。

appletタグのobject属性およびobjectおよびjava objectアプレット・パラメータ・タグは、アプレットの起動時に無視されます。

アプレットをシリアライズするかわりに、通常の方法でデプロイしてください。

JNLP仕様の更新

JNLP (Java Network Launch Protocol)が、不整合の解消、コードのメンテナンス性の向上、セキュリティの強化を目的として更新されました。

JDK 9では、JNLPが次のように更新されました:

  1. JNLPファイルにおける&のかわりの&amp;の使用。

    JNLPファイル構文はXML仕様に準拠しており、すべてのJNLPファイルは標準のXMLパーサーによる解析が可能である必要があります。

    JNLPファイルでは複雑な比較を指定できます。これまでこれはアンパサンド(&)を使用して行われていましたが、これは標準XMLではサポートされていません。&を使用して複雑な比較を作成している場合、JNLPファイルで&amp;に置き換えてください。&amp;はすべてのバージョンのJNLPで互換性があります。

  2. 数値バージョン要素タイプと非数値バージョン要素タイプの比較。

    これまで、intバージョンの要素とintとして解析できない他のバージョンの要素を比較する際は、両者をASCII値として辞書式に比較していました。

    intとして解析できる要素が他の要素より短い文字列である場合、ASCII値に基づいて辞書式に比較する前に先行のゼロが埋め込まれます。これにより循環がないことが保証されます。

    バージョン比較とJNLPサーブレットの両方が使用される場合、数値のみを使用してバージョンを表す必要があります。

  3. java (またはj2se)要素にネストされたリソースがあるコンポーネント拡張機能。

    これは仕様で許可されています。以前もサポートされていましたが、このサポートが仕様に反映されていませんでした。

  4. FX XML拡張。

    JNLP仕様が強化され、type属性がapplication-desc要素に、そしてサブ要素paramapplication-descに(すでにapplet-descにあるように)追加されました。

    JavaFXアプリケーションを指定する以前の方法も引き続きサポートされているため、これが既存のアプリケーションにおいて問題となることはありません。

JSR-056のJNLP仕様の更新に関する項を参照してください。

ガベージ・コレクションへの変更

この項では、JDK 9以降でガベージ・コレクションに加えられた変更について説明します。

デフォルトのガベージ・コレクタがG1に

ガベージファースト・ガベージ・コレクタ(G1 GC)は、JDK 9以降のリリースのデフォルトのガベージ・コレクタです。

大部分のユーザーにとって、G1 GCなどの一時停止の少ないコレクタは、JDK 8のデフォルトであったParallel GCなどのスループット指向のコレクタに比べて全体のパフォーマンスが優れています。

G1 GCのチューニングの詳細は、『Java Platform, Standard Edition HotSpot仮想マシン・ガベージ・コレクション・チューニング・ガイド』G1 GCのエルゴノミック・デフォルトに関する項およびチューニング可能なデフォルトに関する項を参照してください。

削除されたGCオプション

JDK 9以降のリリースでは、次のGCの組合せの場合に、アプリケーションの起動に失敗します。

  • DefNew + CMS
  • ParNew + SerialOld
  • インクリメンタルCMS

CMSのフォアグラウンド・モードも削除されています。削除されたコマンドライン・フラグは、-Xincgc-XX:+CMSIncrementalMode -XX:+UseCMSCompactAtFullCollection-XX:+CMSFullGCsBeforeCompactionおよび -XX:+UseCMSCollectionPassingです。

コマンドライン・フラグ-XX:+UseParNewGCは有効ではなくなりました。ParNewフラグはCMSとともにのみ使用でき、CMSではParNewが必須です。そのため、-XX:+UseParNewGCフラグは非推奨となっており、今後のリリースで削除対象となっています。

『JEP 214: Remove GC Combinations Deprecated in JDK 8』を参照してください。

ノート:

CMSガベージ・コレクタが削除されました。『JEP 363: Remove the Concurrent Mark Sweep (CMS) Garbage Collector』を参照してください。

Permanent世代の削除

Permanent世代はJDK 8で削除されており、関連するVMオプションでは警告が表示されます。次のオプションはスクリプトから削除する必要があります。

  • -XX:MaxPermSize=size

  • -XX:PermSize=size

JDK 9以降のリリースでは、JVMに次のような警告が表示されます。
Java HotSpot(TM) 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0

Permanent世代を認識するツールは更新が必要となる可能性があります。

『JEP 122: Remove the Permanent Generation』およびJDK 9リリース・ノート - 削除されたAPI、機能およびオプションを参照してください。

GCログ出力の変更

ガベージ・コレクション(GC)ロギングではJVM統合ロギング・フレームワークを使用しており、新しいログと古いログとでいくらかの違いがあります。現在使用しているGCログ・パーサーは変更がほぼ必要となります。

さらに、JVMロギング・オプションも更新が必要となる可能性があります。GC関連のすべてのロギングにおいて、通常は他のタグと組み合せて、gcタグを(例: —Xlog:gc)使用する必要があります。—XX:+PrintGCDetailsオプションおよび-XX:+PrintGCオプションは非推奨となっています。

Java Development Kitツール仕様JVM Unified Logging Frameworkによるロギングの有効化に関する項および『JEP 271: Unified GC Logging』を参照してください。

Javaアプレットの実行

引き続きアプレットに依存している場合は、Microsoft EdgeをInternet ExplorerモードでJRE 8とともに使用することで、Windowsシステムでアプレットを起動できる可能性があります。『Microsoft Edge + Internet Explorer mode: Getting Started guide』を参照してください。

2021年9月現在、アプレットの起動に必要なJavaプラグインがJava 8のWindowsで引き続き更新されていますが、今後の更新リリースではいつでも削除される可能性があります。

Oracleのお客様は、My.Oracle.Support Note 251148.1 - Java SE 8 End of Java Plugin Supportで詳細情報を確認できます(ログインが必要)。

正規表現のマッチングにおける動作の変更

java.util.regex.Patternクラスは、大カッコ付きの正規表現で文字クラスを定義します。たとえば、[abc]は、a、bまたはcに一致します。否定の文字クラスは、開始の大カッコの直後にキャレットを付けて定義されます。たとえば、[^abc]は、a、bまたはcを除く任意の文字に一致します。

JDK 8以前では、否定の文字クラスは、ネストされた文字クラスを否定しませんでした。たとえば、[^a-b[c-d]e-f]cに一致しますが、ネストされたクラス内にないため、aまたはeに一致しません。演算子は1つずつ順に適用されます。この例では、ネストの前に否定演算子^が適用されます。JDK 8以前では、演算子^は、文字クラス内の最も外側の文字にのみ適用されますが、ネストされた文字クラスには適用されませんでした。この動作は混乱が生じ、理解するのが困難でした。

しかし、JDK 9以降では、否定演算子はネストされたすべての文字クラスに適用されました。たとえば、[^a-b[c-d]e-f]cに一致しません。

さらに説明するために、次の正規表現を考えてみます:
[^a-d&&c-f]

JDK 8では、^演算子が最初に適用されるため、この例では[^a-d][c-f]と交差していると解釈されます。これは、eおよびfに一致しますが、abcまたはdには一致しません。

JDK 9以降では、&&演算子が最初に適用されるため、この例は[a-d]&&[c-f]の補集合として解釈されます。これは、abeおよびfに一致しますが、cまたはdには一致しません。

ベスト・プラクティスとして、否定、交差およびネストされたクラスを組み合せた文字クラスを使用する正規表現を探します。これらの正規表現は、変更された動作を考慮するために調整が必要になる場合があります。

削除のために非推奨となったセキュリティ・マネージャ

JDK 17では、セキュリティ・マネージャおよびそれに関連するAPIは非推奨であり、今後のリリースでは削除されます。セキュリティ・マネージャの代わりとなるものはありません。詳細および代替手段については、JEP 411を参照してください。