Skip to content

Instantly share code, notes, and snippets.

@wreulicke
Last active February 18, 2018 07:26
Show Gist options
  • Save wreulicke/7bbe4fbf9a4def2ff195e6e00b970d4b to your computer and use it in GitHub Desktop.
Save wreulicke/7bbe4fbf9a4def2ff195e6e00b970d4b to your computer and use it in GitHub Desktop.
マイグレーション用メモ

途中からやる気ないので許して

これはOracle公式のJava9へのマイグレーションに関するポストの和訳です。 翻訳が間違っていたとしても、私は責任を取りませんので その旨を了解した上で、参考程度にご覧になってください。 おかしな点があれば、教えていただければ幸いですが 基本的には本家ポストを読んでください。 https://docs.oracle.com/javase/9/migrate/toc.htm

Migration to Oracle JDK9

このガイドの目的は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を確認してください。

Prepare for Migration

このセクションでは次のステップでマイグレーションの手助けを行います。

  • JDK9 EAを取得する
  • 再コンパイル前にプログラムを実行する
  • サードパーティモジュールをアップデートする
  • アプリケーションをコンパイルする
  • jdepsをあなたのコード上で走らせる

Get the JDK 9 Early Access Build

最新のOracle JDK9 EA releaseをダウンロード・インストールしてください。 EA releaseについてはプロダクション環境では使わず デバッグとテストのみに利用されることを目的としています。

Run Your Program Before Recompiling

JDK9 EAでアプリケーションを動かしてみましょう。 そして何が起きるかを見てみましょう。あなたがJava SEのAPIに限った利用をしているならば 何も変更なく動かすことができるでしょう。


Note:

マイグレーションは逐次的なプロセスです。このタスクを試したのち 多かれ少なかれ次の3つのタスクを並列に行いましょう。

  • サードパーティモジュールをアップデートする
  • アプリケーションをコンパイルする
  • jdepsをあなたのコード上で走らせる

あなたのアプリケーションを動かした時に利用不可能なVMのオプションがJVMによって 警告されるでしょう。 もし、VMの実行が失敗したなら、オプションを外してください。 JDK8で非推奨になったフラグはJDK9にて削除されています。 これについてはRemoved GC Optionsを確認してください。

もし、アプリケーションの実行に成功したなら、注意深くテストを見ることと JDK8の場合と同じ動きかどうかを確かめましょう。何人かのアーリーアダプターによって 日付や通貨のフォーマットの動きが異なることが報告されています。 詳しくはUse CLDR Locale Date by Defaultを確認してください。

Update Third-Party Library

あなたの使うライブラリやツールの全てであなたはJDK9のサポートのためには バージョンのアップデートが必要になるでしょう。

ライブラリやツールの提供者のサイトを確認して Java 9で動作することを設計されているツールやライブラリのバージョンを確認してください。

もしあれば、新しいバージョンをインストールしてください。

もしあなたがIDEを開発に使っているなら、すでにあるコードのマイグレーションを助けることの助けになるでhそう。 すでにIDEにおいてJDK9のサポートがされたバージョンが存在します。

また、あなたは多くのFOSSのテストの状況をOpenJDK wikiの Quality Outreachで確認できるでしょう。

Compile Your Application

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をご確認ください。

Run jdeps on Your Code

アプリケーションでjdepsを実行してください。内部APIを使っていればjdepsは アップデートを支援するために置き換え方針を提案します。

jdepsは静的解析のためのツールで、あなたのアプリケーションやライブラリが依存しているクラスやパッケージが確認するのに助けになるでしょう。 コードの静的解析は全てを知らせるわけではありません。リフレクションによって内部APIを呼び出している場合、jdepsは警告できません。実行時にはIllegalAccessExceptionを見ることになるでしょう。

JDK内部のAPIへの依存を見るために、jdepsに-jdkinternalsオプションを付与して実行してください。 例えば、sun.misc.BASE64Encoderを呼び出しているクラスにjdepsを実行した場合 次のような表示を見るでしょう。

もし、あなたがMavenを使っているならば、jdepsのプラグインが存在します。

jdepsのsyntaxについてはOracleのリファレンスをご覧ください。

もし、あなたがデフォルトでアクセス不可になっている内部APIの利用が必要な箇所があるならば カプセル化を破壊するために、JEP261に記載されているコマンドラインオプションで--add-exportsオプションを記述する必要があります。 このオプションはマイグレーションの目的のみで利用されるべきです。

Changes to the Installed JDK/JRE Image

これらについてはJDK/JREについて知るべき事柄が存在します。

New Version-String Scheme

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をご確認ください。

Changed JDK and JRE Layout

JDK/JREのファイル配置がJDK9で変化しています。

JDK9をインストールしたらファイルシステムが見れるなら、ディレクトリ構成を見ると 前回のバージョンと違うことがわかるでしょう。

以前はかならずJREと分離されており、あなたが実行環境をほしいのであればダウンロートできましたが これは開発用のツールのフルセットではありませんでした。これらはjavaランチャーのようなツールの様々な実行バイナリのサブセットで構成されたjreディレクトリで構成されていました。

もしあなたがソフトウェア開発をするなら、JDKをダウンロードする必要がありました。 以前のリリースまでは同じjreディレクトリを持った、jdkディレクトリとそれらに関するツール、ライブラリの追加が必要でした。jreとjdkのディレクトリの両方はそれぞれ独自にbinディレクトリを持っており、結果としてJDK内部でバイナリが重複しておりました。 加えて、ユーザが編集可能なファイルは様々なディレクトリに分散していました。 エンドユーザーに調整されることが意図されていたファイルとJDK内部のファイルの区別が明確になっておりませんでした。

New Runtime Image Structure

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をご確認ください。

Removed rt.jar and tools.jar

** この辺の和訳少し微妙。気が向いたら見直す。 ** 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では不可能です。

Revemod Extension Mechanism

こんなのあったの?どうせ使わないから翻訳しない

Removed Endorsed Standards Override Mechanism

こんなのあったの?どうせ使わないから翻訳しない(take2)

削除されたAPIs

Removed java.* API

Javaチームは後方互換性を約束します。もし、JDK8で動いていたアプリケーションなら サポートおよび、外部利用を目的とするAPIを使っているならばJDK9でも動くでしょう。

  • これはjava.*, javax.*や
  • JDKの特定のAPIです。com.sun., jdk.

サポートされていたAPIはJDKから削除することが可能ですが、これには告知をします。 静的解析ツールjdeprscanを走らせることによって非推奨のAPIを使っていることを見つけてください。

JDK9で削除されるのは前バージョンで非推奨になった java.util.logging.LogManagerのメソッドとjava.util.jar.Pack200のパッケージです。

Removal and Future Removal of sun.misc and sun.reflect APIs

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.

java.awt.peer Not Accessible

はい。

Removed com.sun.image.codec.jpeg Package

はい。

Removed HTTP Proxy System Properties from RMI

はい。

Use CLDR Locale Data by Default

デフォルト変わったぜ、もともとCOMPATだったみたいだぜ JDKとのコンパチが必要なら設定変えてくれよな

Thread.stop(Throwable) Throws Exception

互換性のためにメソッド残ってるけど、例外投げるようにしたぜ

Removed stopThread RuntimePermission from the Default java.policy

はい。また今度見るよ。 ポリシーのデフォルト設定が変わったみたい。

Deployment

Removed Launch-Time JRE Version Selection

JREに対して-versionのオプションが使えなくなったぜ。

Removed Support for Serialized Applets

はい。

JNLP Specification Update

たぶん知らなくていいやつ。

Changes to Garbage Collection

Make G1 the Default Garbage Collector

デフォルトがG1GCになったよ。

Removed GC Options

オプション削除されたよ

Removed Permanent Generation

パーマネント領域に関する世代管理がなくなったよ?

Changes to GC Log Output

ログ出力の変更

Removed Tools

Removed JavaDB

なくなった。

Removed the JVM TI hprof Agent

余裕があったら読むけど どうせ削除されるからいいよもう。

Removed the jhat Tool

実験的なツールが消えたよ

Removed java-rmi.exe and java-rmi.cgi Launchers

消えました。

Removed Support for the IIOP transport from the JMX RMIConnector

JMX使うなら見るけどRMIの話っぽい。まぁいいや

Dropped Windows 32 Client VM

さよならWindows32

Removed Visual VM

これだけ気になるけどOpen Source Projectのほうから落としてきたら使えるみたい。 (※Visual VM使ったことない。)

Removed native2ascii Tool

こんなのあったの。

Removed macOS-specific Features

まぁいいや

Looking Forward

  • JDK9の何が新しいのかを読むと新しい機能についてわかるよ
  • javacにreleaseオプションが用意されたよ。
  • 最新の機能と一緒にコードを書き換えるためにはIDEが助けてくれるよ
  • jdeps使ったら非推奨のAPIとか調べられるよ

Documentation Accessibility

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment