途中からやる気ないので許して
これはOracle公式のJava9へのマイグレーションに関するポストの和訳です。 翻訳が間違っていたとしても、私は責任を取りませんので その旨を了解した上で、参考程度にご覧になってください。 おかしな点があれば、教えていただければ幸いですが 基本的には本家ポストを読んでください。 https://docs.oracle.com/javase/9/migrate/toc.htm
このガイドの目的はJDK9に既存のアプリケーションをマイグレーションをする際に潜む問題を識別するための手助けをすることとそれらの解決策を示すことです。
新しいJava SEのリリースではいくつかのバイナリ、ソース加えて動作における前バージョンとの非互換性が存在します。Java SEのモジュールシステムはいくつかの利点とともに多くの変更をもたらします。Java SEでサポートされたAPIおよびJDK特有のAPIのみの利用に限ったコードについては変更なしに動きます。 しかし、何等かの機能を使っているコードやJDKの内部APIを使ったコードは 動かない、もしくは異なる結果を示すでしょう。
アプリケーションのマイグレーションには Prepare for Migrationに並べられた次のステップを進めましょう。 そして次にあなたのアプリケーションを動かすために直面するであろう、変更の一覧です。
- インストールしているJDK/JREの変更
- 削除された、変更されたAPI
- デプロイ
- ガベージコレクションへの変更
- 削除されたツール
- MACOS固有の機能
最後にJDK9で動いたアプリケーションについておいても、 Looking Forwardを確認して次のリリースでの問題を避けるのを助けるでしょう。
このガイドはJDK9であなたのコードを動かすために 必要とされる変更に注視しています。 JDK9で増える機能の全ての包括的なリストについては What's New in JDK9を確認してください。
このセクションでは次のステップでマイグレーションの手助けを行います。
- JDK9 EAを取得する
- 再コンパイル前にプログラムを実行する
- サードパーティモジュールをアップデートする
- アプリケーションをコンパイルする
- jdepsをあなたのコード上で走らせる
最新のOracle JDK9 EA releaseをダウンロード・インストールしてください。 EA releaseについてはプロダクション環境では使わず デバッグとテストのみに利用されることを目的としています。
JDK9 EAでアプリケーションを動かしてみましょう。 そして何が起きるかを見てみましょう。あなたがJava SEのAPIに限った利用をしているならば 何も変更なく動かすことができるでしょう。
マイグレーションは逐次的なプロセスです。このタスクを試したのち 多かれ少なかれ次の3つのタスクを並列に行いましょう。
- サードパーティモジュールをアップデートする
- アプリケーションをコンパイルする
- jdepsをあなたのコード上で走らせる
あなたのアプリケーションを動かした時に利用不可能なVMのオプションがJVMによって 警告されるでしょう。 もし、VMの実行が失敗したなら、オプションを外してください。 JDK8で非推奨になったフラグはJDK9にて削除されています。 これについてはRemoved GC Optionsを確認してください。
もし、アプリケーションの実行に成功したなら、注意深くテストを見ることと JDK8の場合と同じ動きかどうかを確かめましょう。何人かのアーリーアダプターによって 日付や通貨のフォーマットの動きが異なることが報告されています。 詳しくはUse CLDR Locale Date by Defaultを確認してください。
あなたの使うライブラリやツールの全てであなたはJDK9のサポートのためには バージョンのアップデートが必要になるでしょう。
ライブラリやツールの提供者のサイトを確認して Java 9で動作することを設計されているツールやライブラリのバージョンを確認してください。
もしあれば、新しいバージョンをインストールしてください。
もしあなたがIDEを開発に使っているなら、すでにあるコードのマイグレーションを助けることの助けになるでhそう。 すでにIDEにおいてJDK9のサポートがされたバージョンが存在します。
また、あなたは多くのFOSSのテストの状況をOpenJDK wikiの Quality Outreachで確認できるでしょう。
JDK9のコンパイラでコードをコンパイルしてみて警告やエラーを確認しましょう。 JDK9特有のいくつかの理由でコンパイルが失敗するかもしれません。
-
JDK内部のAPIの多くはデフォルトではアクセス不可になっています。 コンパイルエラーや実行時にIllegalAccessErrorが得られた場合 それはあなたのアプリケーションもしくはライブラリが 内部APIに依存していることを示しています。
この依存を調べるにはJavaの依存関係解析ツールを使いましょう。詳しくは Run jdeps on Your Codeを確認してください。可能であれば、サポートされている置き換えられたAPIを使うようにアップデートしてください。 コンパイル時の警告を手掛かりにチェックしてください。以前よりも多くの非推奨のエラーが見られることがあります。もし、削除の警告がある非推奨があるなら あなたは将来の問題を避けるために対処する必要があるでしょう。
-
もしあなたがアンダースコア1文字の識別子をソースコードで用いているならば、JDK9ではコンパイルできません。 これはJDK8では警告が出ており、JDK9ではエラーとなります。
これは次のようなコードで コンパイラーからは次のようなエラーメッセージが表示されます。
*** 省略 ***
- もしあなたがjavacのコンパイルオプションでバージョンの指定をしているならば指定している値を確認してください。JDK9ではバージョンに関してone plus three backポリシーの基にサポートしています。
ソースとターゲットは9、8、7、そして非推奨で警告を出す6をサポートされています。
JDK8ではソースとターゲットに関して、1.5は非推奨としており、警告を出していますが JDK9ではエラーとしています。
可能であれば、新しいreleaseフラグをsource, targetの代わりに利用してください。 sourceとtargetのマクロとして働きます。
releaseオプションに関してもsource, targetと同じポリシーが適用されます。 javacは以前のJDKで処理されたクラスファイルを認識することができ、JDK1.0.2まで遡って認識することが可能です。
これについてはJEP 182: Policy for Retiring javac -source and -target Optionsをご確認ください。
アプリケーションでjdepsを実行してください。内部APIを使っていればjdepsは アップデートを支援するために置き換え方針を提案します。
jdepsは静的解析のためのツールで、あなたのアプリケーションやライブラリが依存しているクラスやパッケージが確認するのに助けになるでしょう。 コードの静的解析は全てを知らせるわけではありません。リフレクションによって内部APIを呼び出している場合、jdepsは警告できません。実行時にはIllegalAccessExceptionを見ることになるでしょう。
JDK内部のAPIへの依存を見るために、jdepsに-jdkinternalsオプションを付与して実行してください。 例えば、sun.misc.BASE64Encoderを呼び出しているクラスにjdepsを実行した場合 次のような表示を見るでしょう。
もし、あなたがMavenを使っているならば、jdepsのプラグインが存在します。
jdepsのsyntaxについてはOracleのリファレンスをご覧ください。
もし、あなたがデフォルトでアクセス不可になっている内部APIの利用が必要な箇所があるならば カプセル化を破壊するために、JEP261に記載されているコマンドラインオプションで--add-exportsオプションを記述する必要があります。 このオプションはマイグレーションの目的のみで利用されるべきです。
これらについてはJDK/JREについて知るべき事柄が存在します。
JDK9ではバージョンのフォーマットが簡略化されます。もし、あなたがバージョンの文字列表現によって、バージョンの判断をしているならば その部分に関して修正が必要になるでしょう。
新しいバージョンのフォーマットは次のフォーマットになります。
$MAJOR.$MINOR.$SECURITY.$PATCH
例えば、古いスキーマでは9u5のreleaseは1.9.0_5-b20.と表記されていましたが 新しいSchemaでは短い表記では9.0.1、長い表記では9.0.1+20と表記されます。
この変更の影響はjava -versionとシステムプロパティに影響します。
- java.runtime.version, java.vm.version
- java.specification.version
- java.vm.specification.version
バージョンの比較や検証のための簡単なJavaAPIが追加されています。 これに関してはjava.lang.Runtimeを確認してください。
Version String Format (Java Platform, Standard Edition Installation Guide )や JEP 223: New Version-String Schemeをご確認ください。
JDK/JREのファイル配置がJDK9で変化しています。
JDK9をインストールしたらファイルシステムが見れるなら、ディレクトリ構成を見ると 前回のバージョンと違うことがわかるでしょう。
以前はかならずJREと分離されており、あなたが実行環境をほしいのであればダウンロートできましたが これは開発用のツールのフルセットではありませんでした。これらはjavaランチャーのようなツールの様々な実行バイナリのサブセットで構成されたjreディレクトリで構成されていました。
もしあなたがソフトウェア開発をするなら、JDKをダウンロードする必要がありました。 以前のリリースまでは同じjreディレクトリを持った、jdkディレクトリとそれらに関するツール、ライブラリの追加が必要でした。jreとjdkのディレクトリの両方はそれぞれ独自にbinディレクトリを持っており、結果としてJDK内部でバイナリが重複しておりました。 加えて、ユーザが編集可能なファイルは様々なディレクトリに分散していました。 エンドユーザーに調整されることが意図されていたファイルとJDK内部のファイルの区別が明確になっておりませんでした。
JDK9において、JDKとJREの2つの実行モジュールはそれぞれ次のディレクトリ含みます。
- bin 実行バイナリのフォルダ
- conf propertiesやconfなどの開発者によって編集されることを意図するその他のファイル(以前は別のlibやそのサブディレクトリにあった編集されることのあるファイルもここ)
- lib 実行時に動的にlinkされるライブラリと完全にJDK内部の実装
JDKとJREのダウンロードは以前、分かれていますが ダウンロードしたイメージに関係なく同じ構造になっています。 JDK imageはjavacのような外部ツールやJDKにもともとあるようなライブラリを含みます。 もうjdkがjreをwrapするようなディレクトリ構成は無く、バイナリの重複はありません。
詳しくはJEP220 Modular Run-Time Imagesをご確認ください。
** この辺の和訳少し微妙。気が向いたら見直す。 ** rt.jarやtools.jar、dt.jarなどに含まれていたクラスやリソースやその他の内部jarファイルは より効率的な形式でlibディレクトリに実装特有のファイルとして配置されています。
rt.jarやそれらのファイルの削除は次のような問題を引き起こします。
-
JDK9ではClassLoader::getSystemResourceはjar fileを示すURLを返却しません。(jarがないために) その代わり、正しいURLを返却します。例えばJDK8では次のコードでは次のURLの形式で返却されておりました。
** 省略 **
実行のイメージに実際のjarファイルの名前が埋め込まれています。URLオブジェクトのメソッドによってクラスファイルの情報を取得するために使うことができました(組み込みのプロトコルハンドラを利用することで) モジューラー imageは他のjarを含みません。そのため上記URLは何も意味を為しません。
java.security.CodeSource APIとセキュリティポリシーファイルをを使うことで特別な権限を与えるためにコードベースの場所の名前付けられたURLを使うことができます。 詳細はPolicy File Syntaxをご確認ください。ランタイムシステムの特定の許可が必要となるコンポーネントはファイルURLを介して、policyファイルによって識別されます。
IDEやその他開発ツールは実行イメージに格納されているクラスやリソースを列挙しをrt.jarなどのファイルを直接開いて読み込む機能が必要になります。これはモジュラーimageでは不可能です。
こんなのあったの?どうせ使わないから翻訳しない
こんなのあったの?どうせ使わないから翻訳しない(take2)
Javaチームは後方互換性を約束します。もし、JDK8で動いていたアプリケーションなら サポートおよび、外部利用を目的とするAPIを使っているならばJDK9でも動くでしょう。
- これはjava.*, javax.*や
- JDKの特定のAPIです。com.sun., jdk.
サポートされていたAPIはJDKから削除することが可能ですが、これには告知をします。 静的解析ツールjdeprscanを走らせることによって非推奨のAPIを使っていることを見つけてください。
JDK9で削除されるのは前バージョンで非推奨になった java.util.logging.LogManagerのメソッドとjava.util.jar.Pack200のパッケージです。
JDK9は多くの内部APIはデフォルトではアクセス不可にしていますが、いくつかの汎用的内部APIのアクセスは可能のままです。これはそれらの機能の全てもしくはほとんどの大体がサポートされるまでの間です。
いくつかのsun.* APIはJDK9で削除されました。注目すべきはBASE64Encoder、Decoderが削除されています。代わりにJDK8で用意されたBase64クラスを利用してください。
sun.misc, sun.reflectのパッケージでJDK9でアクセス可能のままなAPIは次になります
- sun.misc.{Signal,SignalHandler}.
- sun.misc.Unsafe. The functionality of many of the methods in this class is now available via variable handles, see JEP 193: Variable Handles.
- sun.reflect.Reflection::getCallerClass(int). Instead, use the stack-walking API, see JEP 259: Stack-Walking API.
- sun.reflect.ReflectionFactory.newConstructorForSerialization.
はい。
はい。
はい。
デフォルト変わったぜ、もともとCOMPATだったみたいだぜ JDKとのコンパチが必要なら設定変えてくれよな
互換性のためにメソッド残ってるけど、例外投げるようにしたぜ
はい。また今度見るよ。 ポリシーのデフォルト設定が変わったみたい。
JREに対して-versionのオプションが使えなくなったぜ。
はい。
たぶん知らなくていいやつ。
デフォルトがG1GCになったよ。
オプション削除されたよ
パーマネント領域に関する世代管理がなくなったよ?
ログ出力の変更
なくなった。
余裕があったら読むけど どうせ削除されるからいいよもう。
実験的なツールが消えたよ
消えました。
JMX使うなら見るけどRMIの話っぽい。まぁいいや
さよならWindows32
これだけ気になるけどOpen Source Projectのほうから落としてきたら使えるみたい。 (※Visual VM使ったことない。)
こんなのあったの。
まぁいいや
- JDK9の何が新しいのかを読むと新しい機能についてわかるよ
- javacにreleaseオプションが用意されたよ。
- 最新の機能と一緒にコードを書き換えるためにはIDEが助けてくれるよ
- jdeps使ったら非推奨のAPIとか調べられるよ