6 移行の準備

次の項は、アプリケーションの移行を成功させるのに役立ちます。

最新のJDKのダウンロード

Java SEダウンロードから最新のJDKリリースをダウンロードしてインストールします。

デフォルトの文字セット

デフォルトのcharsetは、UTF-8です。ただし、JDK 17以前のリリースでは、デフォルトの文字セットはJavaランタイムの起動時に決定されます。つまり、macOSでは、POSIX Cロケール以外で使用されるデフォルトの文字セットはUTF-8になります。他のオペレーティング・システムでは、ユーザーのロケールおよびデフォルトのエンコーディングに依存していました。たとえば、Windowsでは、windows-1252windows-31jなどのコードページ・ベースの文字セットです。メソッドjava.nio.charsets.Charset.defaultCharset()は、デフォルトの文字セットを返します。

次のコマンドを実行して、JDK 17以前のリリースでデフォルトの文字セットとして使用される文字セットを確認します:
java -XshowSettings:properties -version 2>&1 | grep native.encoding

検出されたエンコーディングがUTF-8と異なる場合、環境で実行されているアプリケーションが影響を受ける可能性があります。

JDKのデフォルトの文字セットの変更

環境が影響を受ける場合は、システム・プロパティfile.encodingを使用してさらに調査します。コマンドラインの値を次のいずれかに設定します:
  • UTF-8: デフォルトの文字セットはUTF-8です。
  • COMPAT: デフォルトの文字セットは、JDK 17以前のリリースと同じように決定されます。

file.encodingのその他の値はサポートされません。

ノート:

  • 既存のJDKを使用してコマンドjava -Dfile.encoding=UTF-8 <your application>を実行します。これにより、JDK 18以降と同じ環境が提供されます。差異があるかどうかを確認します。
  • JDK 18以降でコマンド-Dfile.encoding=COMPAT <your application>を実行して、以前の動作を取得し、差異があるかどうかを確認します。

詳細は、『Java Platform, Standard Edition国際化ガイド』デフォルトの文字セットに関する項を参照してください。

再コンパイルする前のプログラムの実行

最新のJDKリリース(JDK 18)でアプリケーションを実行します。たいていのコードおよびライブラリは変更しなくてもJDK 18上で動作するはずですが、一部のライブラリはアップグレードの必要があります。

ノート:

移行は反復的なプロセスです。プログラムをまず実行してみてから(このタスク)、これらの3つのタスクを平行して進めるのがおそらく最善でしょう:

アプリケーションの実行時に、廃止されたVMオプションに関するJVMからの警告がないか確認します。VMの起動に失敗する場合は、「削除されたGCオプション」を確認してください。

アプリケーションが正常に起動する場合は、慎重にテストして動作が使用中のJDKバージョンのときと同じであることを確認します。たとえば、一部の早期導入者は日付および通貨の形式が違っていることに気付いてきました。「デフォルトでのCLDRロケール・データの使用」を参照してください。

最新のJDKリリースでコードを動作させるには、各JDKリリースの新機能および変更点を確認します。

プログラムが正常に動作しているようであっても、このガイドの残りのステップを完了して問題のリストを確認するようにしてください。

サードパーティ・ライブラリの更新

使用するすべてのツールおよびサードパーティ・ライブラリについて、最新のJDKリリースをサポートする更新版が必要となる可能性があります。

最新のJDKで動作するように設計された各ライブラリまたはツールのバージョンについては、サードパーティ・ライブラリおよびツール・ベンダーのWebサイトを確認してください。提供されている場合は、その新しいバージョンをダウンロードおよびインストールしてください。

MavenまたはGradleを使用してアプリケーションを構築している場合は、最新のJDKバージョンをサポートしている最近のバージョンにアップグレードしてください。

IDEを使用してアプリケーションを開発している場合は、既存のコードを移行するのに役立ちます。NetBeans、EclipseおよびIntelliJのIDEはいずれも、最新のJDKのサポートを含むバージョンが提供されています。

OpenJDK Wikiの品質支援に関する項で、多くのフリー・オープン・ソース・ソフトウェア(FOSS)プロジェクトをテストしたステータスを確認できます。

アプリケーションのコンパイル(必要に応じて)

問題があることがわかっているAPIや機能にコードが依存している可能性があるため、最新のJDKコンパイラでコードをコンパイルすると、将来のリリースへの移行が容易になります。ただし、必ず必要というわけではありません。

コードをJDK 11以降のコンパイラでコンパイルする必要がある場合、次の点に注意してください。

  • ソース・コードでアンダスコア文字("_")を一文字で識別子として使用している場合、JDK 11以降のリリースではそのコードはコンパイルできません。このように使用するとJDK 8では警告となり、JDK 9以降ではエラーとなります。

    次に例を示します:

    static Object _ = new Object();

    このコードではコンパイラにより次のエラー・メッセージが生成されます。

    MyClass.java:2: error: as of release 9, '_' is a keyword, and may not be used as a legal identifier.
    
  • javac-sourceおよび-targetオプションを使用する場合、使用する値を確認してください。

    -source/-targetのサポートされている値は、18 (デフォルト)、17、16、15、14、13、12、11、10、9、8および7です。

    JDK 8では、-sourceおよび-targetの値に1.5/5以前の値を指定するのは非推奨となり、警告が表示されました。JDK 9以降では、これらの値はエラーになります。

    >javac -source 5 -target 5 Sample.java 
    warning: [options] bootstrap class path not set in conjunction with -source 5 
    error: Source option 5 is no longer supported. Use 6 or later. 
    error: Target option 1.5 is no longer supported. Use 1.6 or later.

    -sourceおよび-targetオプションのかわりに新しい--releaseフラグを使用します。Java Development Kitツール仕様javacに関する項を参照してください。

    --releaseフラグの有効な引数には、-sourceおよび-targetと同じく、"one plus three back"ポリシーが適用されます。

    javacは、JDK 1.0.2クラス・ファイルまでさかのぼる、以前のすべてのJDKのクラス・ファイルを認識および処理できます。

    『JEP 182: Policy for Retiring javac -source and -target Options』を参照してください。

  • sun.misc.Unsafeなどの重要な内部JDK APIにはJDK 11以降でも引き続きアクセスできますが、JDKの大部分の内部APIにはコンパイル時にはアクセスできません。アプリケーションまたはそのライブラリが内部APIに依存していることを示すコンパイル・エラーが発生することがあります。

    依存関係を特定するには、Java依存性分析ツールを実行します。「コードに対するjdepsの実行」を参照してください。可能であれば、サポートされている代替APIを使用するようにコードを更新してください。

    JDK内部クラスへの参照があるソース・コードをコンパイルするための一時的な回避策として、--add-exportsおよび--add-opensオプションを使用できます。これらのオプションの詳細は、JEP 261: モジュール・システムに関する項および「JDK内の強力なカプセル化」を参照してください。

  • 以前より多くの非推奨メッセージが表示される可能性があります。

コードに対するjdepsの実行

アプリケーションに対してjdepsツールを実行して、アプリケーションおよびライブラリが依存するパッケージおよびクラスを確認します。内部APIを使用している場合、jdepsにより、コードを更新する際に役立つ修正候補が表示されることがあります。

内部JDK APIの依存性を検出するには、jdeps-jdkinternalsオプションとともに実行します。たとえば、sun.misc.BASE64Encoderを呼び出すクラスに対してjdepsを実行すると、次のように表示されます。

>jdeps -jdkinternals Sample.class
Sample.class -> JDK removed internal API
   Sample  -> sun.misc.BASE64Encoder  JDK internal API (JDK removed internal API)

Warning: JDK internal APIs are unsupported and private to JDK implementation that are
subject to be removed or changed incompatibly and could break your application.
Please modify your code to eliminate dependency on any JDK internal APIs.
For the most recent update on JDK internal API replacements, please check:
https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool

JDK Internal API                         Suggested Replacement
----------------                         ---------------------
sun.misc.BASE64Encoder                   Use java.util.Base64 @since 1.8

Mavenを使用している場合、利用可能なjdepsプラグインがあります。

jdepsの構文は、Java Development Kitツール仕様jdepsに関する項を参照してください。

jdepsは静的分析ツールであり、コードの静的分析では依存性の完全なリストが得られない可能性があることに注意してください。コードでリフレクションを使用して内部APIが呼び出されている場合、jdepsでは警告は表示されません。