Migration Guide from Java 8 to Java 11
KUBOTA Yuji (@sugarlife)
LINE Corporation
JJUG CCC 2018 Fall (2018/Dec/15)
KUBOTA Yuji (@sugarlife)
JVM好き, IcedTea committer / OpenJDK Author
WEB+DBで連載「Dive to Java」執筆中
https://www.slideshare.net/YujiKubota/
2
前置き
本資料は jdk.java.net/11 からダウンロードできる JDK 11.0.1
で極⼒動作確認していますが、全ては確認はできていませんので
お使いのコードを修正する前に動作確認してください
実装は hg.openjdk.java.net/jdk-updates/jdk11u で確認しています
3
本セッションで話すこと
Java 8からJava 11へのマイグレーション⽅法
基本的なステップ
特に影響が⼤きい⾮互換性の紹介
本セッションで話さないこと
新機能
モジュール化 (Modularize)
⾮互換性の網羅的な紹介
Java 10: git.io/jdk10, Java 11: git.io/jdk11
4
マイグレーションの障壁
互換性
source: translating source file into class file
binary: preserving the link without error
behavioral: code semantics executes at runtime
{Deperecated | Removed | Changed}による⾮互換性が⽣じる
APIs
Options, JVM behavior/stdout/stderr
Tools, certificates, etc...
5
Javaの⾮互換性ポリシー
APIは最短2バージョンで消える
Deprecated -> Removed
@Deprecated(since=9, forRemoval=true) ]
Deprecatedに関するドキュメント
コンパイルは3バージョン前までサポート
JEP 182: Policy for Retiring javac -source and -target
Options
オプションもDeprecatedを経て削除されるのが「慣習」
6バージョンごとのLTSのみ使っている場合はいきなり消える
6
⾮互換性の追い⽅
Issue tracker (primary source)
Java Enhance Proposals(Java 9, Java 10, Java 11)
Compatibility & Specification Review (Java 10, Java 11)
Release Notes (Java 9, Java 10, Java 11)
Source repository (Java 9 GA, Java 10 GA, Java 11 GA)
Migration Guide (Java 9, Java 10, Java 11)
原⽂(Java 9, Java 10, Java 11)
7
Migration steps
1. Run your existing application with Java 11
2. Compile your application with Java 11
3. Modularize your application
8
Migration steps
1. Run your existing application with Java 11 and Test
2. Compile your application with Java 11 and Test
3. Modularize your application
9
Migration steps
1. Run your existing application with Java 11 and Test
2. Compile your application with Java 11 and Test
3. Modularize your application
10
Why not "Modularize" at this time
classpath と modulepath
コストとメリット
Project Portla
JDK内部はモジュール化されたのでその対応は必要
11
1. Run your existing application with Java 11
Java 11で実⾏してテストが通るようにする
新たにコンパイルはしない
12
メリット・デメリット
Good
Full support for Java 8
Free Flight Recorder, AppCDS
TLS 1.3 + Improved security
Full support for Linux containers
Parallel Full GC on G1
New experimental GCs: Epsilon and ZGC
Improved VM performance
Bad
Future migration cost for source/binary incompatibilities
(Support) license changes
13
主な対処内容
実⾏時例外
Removed options
Removed APIs
JDK Internal APIs
Reflection
実⾏時の動作不整合・パフォーマンス
Behavioral incompatibilities
Linux Container
Default GC
14
実⾏時例外
⼤きく分けて以下の⼆種類
Java オプションが古くて起動直後にエラーや警告が出る
クラスやメンバが呼び出せなくてエラーが出る
15
Removed options
Unrecognized option: <option>
完全に削除されて存在しないためエラー(JVM起動に失敗)
Ignoring option <option>; support was removed in 11.0
廃⽌されたため無視される (Obsolete) ⼀覧
<option> was deprecated in version 11.0 and will likely be
removed in a future release.
⾮推奨で将来的に削除予定 (Deprecated) ⼀覧
Invalid -Xlog option
JEP 158: Unified JVM Logging (document)
Unified JVM Logging以外は基本的に代替はなく削除するしかない
16
完全に削除されたオプション例
⼀部を除いて殆ど利⽤されていないオプションが削除されている
-d32 / -d64
-Xoss -Xsqnopause -Xoptimize -Xboundthreads -Xusealtsigs
AdjustConcurrency , PrintJVMWarnings
-Xincgc , CMSIncrementalMode , ...
UnlockCommercialFeatures , LogCommercialFeatures
ロギング関連のオプション( TraceYoungGenTime 等)はよく利⽤され
つつも削除されたが、 -Xlog に置き換わっただけで実害はない
17
Unified JVM Logging
https://www.slideshare.net/YujiKubota/unified-jvm-logging/56
18
Removed APIs
下記のようなクラスがない系のエラーが出た場合、再コンパイル
せずに解決できる代表的なパターンが4つある
java.lang.NoClassDefFoundError: <package>/<class>
java.lang.ClassNotFoundException: <package>/<class>
1. JEP 320よりJava EE及びCORBA関連モジュールが削除された
2. Oracle JDKからJavaFXが削除された
3. モジュール化に伴いJDK Internal APIアクセス厳格化
4. モジュール化に伴いReflectionを⽤いたアクセス厳格化
19
JEP 320: Remove the Java EE and CORBA Modules (1/2)
CORBA以外はスタンドアロンで動作する代替ライブラリを⽤意す
れば実⾏可能
Java 8 パッケージ 代替ライブラリ(アーティファクト)
JAF javax.activation com.sun.activation:javax.activation
JTA javax.transaction javax.transaction:javax.transaction-api ※1
JAXB javax.xml.bind.*
javax.xml.bind:jaxb-api ,
com.sun.xml.bind:jaxb-core ,
com.sun.xml.bind:jaxb-impl ※2
※1: `javax.transaction.xa`が含まれない 1.3 以降必須
(JDK-8197533: Split java.sql to create module java.transaction.xaへの対応)
※2: JAF (`java.activation`) に依存しているのでJAFも追加が必要
20
JEP 320: Remove the Java EE and CORBA Modules (2/2)
Java 8 パッケージ
代替ライブラリ
(アーティファクト)
JAX-WS,
SAAJ
javax.xml.ws.* , javax.jws ,
javax.jws.soap ,
javax.xml.soap
com.sun.xml.ws:jaxws-ri
Common
Annotations
javax.annotation
javax.annotation:javax.annotation-
api
CORBA
javax.activity , javax.rmi ,
javax.rmi.CORBA , org.omg.*
※3
Java 9で --add-modules する解決策を提⽰している記事も多い(※4)
が、Java 11以降はモジュール⾃体が削除されているため使えない
※3: GlassFishプロジェクトが提供しているCORBAライブラリなどもある
※4: Java 9の時点では正しい⽅法であり記事が誤りというわけではない
21
Oracle JDKからJavaFXが削除された
javafx/... から始まるクラスがないエラー等はJavaFXがOracle
JDKから削除されたことが原因。なおOracle JDK以外は元々無い
JavaFXのオープン実装 OpenJFX を利⽤することで解決できる。
Maven Centralにも登録されている
22
JDK Internal APIs
sun.* , com.sun.* , java.awt.peer
jdeps ツールを使えば利⽤しているか調べられる
jdeps --jdk-internals <class/jar...>
java(c) --add-export <module>/<package>=ALL-UNNAMED
<package> は jdeps の結果から解る
<module> はJavaDocなどから確認
ALL-UNNAMED はモジュール化されてないライブラリ
根本的には「使わない」 or 「提供された移⾏先に移る」よう
にコーディングし直して再コンパイルが必要
sun.misc.Unsafe.defineClass → java.lang.invoke.MethodHandles.Lookup.
defineClass , sun.misc.BASE64Encoder → java.util.Base64 等
使い続ける場合も⼀部は jdk.internal* パッケージに移動してるので注意
23
JDK Internal APIs (地獄の釜)
Java 9以降は基本的に移⾏先が提供されている(はず)
問題は Java 8 かつ Java 9 以降でも動くようにするケース
リフレクションを利⽤して移⾏後APIを呼ぶ
例外が起きたら移⾏前APIをリフレクション経由で呼ぶ
ReflectiveOperationException, RuntimeException
例︓LUCENE-6989, HADOOP-12760
後者のIssueを修正した⽅の⽇本語解説資料
24
Reflection
リフレクションを⽤いるとJDK Internal APIやPrivateなメンバにア
クセス可能だが、JDKモジュール化に伴い原則禁⽌された
--add-opens <module>/<package>=<module> 追加で解消可能
左辺はアクセス先のmodule/package、右辺はアクセス元
従来のモジュール化されてないライブラリからアクセス
する場合は右辺に ALL-UNNAMED を指定する
publicなメンバにアクセスする場合は --add-export を追加
根本解決はその様なリフレクションを⾏わないこと。つまりJava 8
とJava 11以降を同時にサポートし続ける限り付きまとう問題
25
JDKモジュール化に伴うモジュールが⾒つからないエラー
クラスパスに含めているパッケージなのに次のエラーが出る場合
は、エラーに応じて対処が必要
package <package> is declared in module <module>, which is
not in the module graph
--add-modules <module>
アプリをモジュール化しない限りは基本的に出ないはず
package <package> is declared in module <module>, which
does not export it...
--add-exports <module>/<package>=ALL-UNNAMED
module <module> does not "open <package>" to the unnamed
module
--add-opens <module>/<package>=ALL-UNNAMED
下2つは主にJDK Internal APIやリフレクション関係で出る
26
それでもクラスなどが⾒つからない系エラーが起きる
例︓java.lang.ClassNotFoundException,
java.lang.NoClassDefFoundError,
java.lang.NoSuchMethodError, java.lang.NoSuchFieldError
特に標準APIが⾒つからない場合は、削除されてる可能性が⾼い
Java EEやJavaFXとは異なり代替ライブラリを⽤意すれば解決する
ものではないので、コードを修正してコンパイルからやり直す必
要がある
27
Bye Applet, Java Web Start
AppletおよびJava Web Startは削除された(Oracleのwhite paper)
Java Web Startの代替となり得るOSSとしては
icedtea-web
GetDown
update4j
が、挙げられるが検証コストやサポートとのトレードオフとなる
28
実⾏の動作不整合・パフォーマンス
CIや性能試験等で確認すべき。性能⾯で特に注意すべきなのは以下
Linux コンテナ対応が⾏われた
コンテナに割り当てられているCPU・メモリに応じて適切
に利⽤するようになった
-XX:-ContainerSupport で戻せる
デフォルトのGCが変わった
Parallel GCからG1 GCに変更された
-XX:+UseParallelOldGC で戻せる
CMS GCはひっそりと⾮推奨になりました
29
しゃべくり GC戦国時代
Serial / Parallel GC
CMS GC
G1 GC
ZGC (Java 11)
Epsilon GC (Java 11)
Shenandoah GC (Java 12)
C4 GC (Azul Zing)
30
動作の不整合例
数字、⽇付、時間フォーマットが変わった
-Djava.locale.providers=COMPAT,SPI,CLDR で戻せる
Phantom参照がクリアされるようになった
実害はないが監視での現れ⽅は変わる。もし
PhantomReference を利⽤していた場合は要注意
Reference::clone は廃⽌され CloneNotSupportedException を
常に投げるようになった
コンストラクタを呼んでインスタンスを作り直そう
java.net.URLClassLoader のコンストラクタに渡されたURLに
null要素が含まれていた場合、 NullPointerException を投げる
ようになった
null 要素がなければOK
31
動作の不整合例
Extension Mechanism と Endorsed Standards Override
Mechanism が廃⽌された
ライブラリを置き換える仕組みがあったが廃⽌された
今後は --classpath で全て指定しましょう
-Xbootclasspath/a で空要素指定は拒否されるようになった
CWD だと読み替えてくれたが今後は拒否される
java.lang.invoke.MethodHandles.filterArguments は引数とし
て渡されたフィルターを左から順に呼び出す仕様であった
が、実際は右から順に呼び出していた
修正されて左から呼ばれるようになった
32
動作の不整合例
Nashornとjjsツールが⾮推奨化
-Dnashorn.args=--no-deprecation-warning で警告オフ
将来的には削除されるので載せ替えるべき
SwingがデフォルトでGTK 3を使うため⾒た⽬が変わった
-Djdk.gtk.version=2.2 を設定すれば元と同じ⾒た⽬
SNMP Agentが削除された
回避策なし、JDK以外のSNMP Agentを利⽤する
java.home , user.home , user.dir , user.name が変更不可
起動時にキャッシュされるようになった
33
動作の不整合例
java.nio.channels.
{SocketChannel,ServerSocketChannel,DatagramChannel,Pipe.Sou
rceChannel,Pipe.SinkChannel} はリファクタリングされてブロ
ッキング・ノンブロッキング処理を分離した
Selectorで登録されていたSocketChannelを閉じた際、こ
のChannelが登録されている全てのSelectorからflushされ
るまで接続を閉じる処理が⼀貫して遅くなる
ノンブロッキングなChannelでI/O操作を呼び出すと割り
込みステータスが設定されChannelが閉じられなくなった
configureBlocking(false) メソッドを呼び出すと、未処理
のブロッキングI/O操作が完了するまで待機する(ブロック
される)ようになった
34
2. Compile your application with Java 11
Java 11でコンパイル&実⾏してテストが通るようにする
35
メリット・デメリット
Good
New / Improved APIs
var
Reactive streams APIs
Unmodifiable collection APIs
Improved file API, system process API
HTTP/2, Async HTTP client
Bad
Java 8のサポートが難しくなる
依存ライブラリのアップデートコストがより掛かる
実⾏環境だけではなくコンパイルとテスト環境
binary compatibilityの破壊
(Support) license changes
36
主な対処内容
コンパイル / テスト環境整備
殆どのライブラリやプラグインを更新する必要がある
残念ながら⼀部はまだバグが残されている
コンパイル時例外・警告
source / binary incompatibilities
JavaDoc
37
コンパイル / テスト環境整備
JDKモジュール化、Abstract Syntax Tree処理変更、バイトコードの
厳格化や出⼒変更に伴い、多くのビルド・テストツールはアップ
デートが必須
特にバイトコードを扱うツール(ASM bytecode manipulationや
javap classfile inspection等)はJava 11でも⼤きな変更が⼊ったた
め、Java 11サポートを待つ必要性が⾼い
Mavenの場合
Maven v3.5.4 以降を利⽤する
プラグインも v3.x 系を利⽤するケースが多い
maven-compiler-plugin with asm dependency
maven-surefire-plugin with asm dependency
38
テスト関係
mockito 等のテストツールに加え javassist 等のBCIツールもア
ップデート必須
開発が衰退/停⽌したライブラリからの移⾏も検討が必要
FindBugs → SpotBugs
Cobertura → JaCoCo
JavaDoc関係
HTML5対応やdoclet削除、JDKモジュール化に伴う"package-
list"から"element-list"へのフォーマット変更などが⾏われた
-link で指定していたURLにアクセスできなくなった場合、警
告ではなくエラーが発⽣して出⼒されない
⾃⼒で解決するのは厳しいのでmaven-javadoc-pluginなどの
ビルドツールやIDEのサポートを待つのが賢明
39
しゃべくり バイトコードに関する変更例
JDK-8010319: Implementation of JEP 181: Nest-Based Access
Control
JDK-8157181: Compilers accept modification of final fields
outside initializer methods
JDK-8057919: Class.getSimpleName() should work for non-JLS
compliant class names
40
コンパイル時例外・警告
⼤きく分けて以下の⼆種類
ソースやバイナリレベルの⾮互換性によりエラーが出る
⾮推奨化(Deprecated)により警告が出る
基本的に不要なAPIを削除してるので、実⾏時例外と⽐較すると回
避策はあまり⽤意されていない。⾮推奨APIは jdeprscan や jdeps
ツール、IDEを駆使して対処するのが楽
41
ソースレベルの⾮互換性
動作の不整合例にも多く載せているのでそちらも確認しよう
"_" を変数名に使えない
唯⼀⽐較的影響が広い&対処⽅法が明確
新元号
java.time.chrono.JapaneseEra.of(3).getDisplayName(java
.time.format.TextStyle.FULL, Locale.JAPAN) => "元号"
今は"元号" (Locale.JAPAN) や "NewEra" (Locale.US) が出⼒
される
元号が決まり次第にアップデートされる予定だが間に合
わないのがほぼ確定してしまってる
com.sun.awt.AWTUtilities クラスが削除された
正攻法に javax.swing.JFrame を使おう
42
まとめ
43
Migration Guide from Java 8 to Java 11
KUBOTA Yuji (@sugarlife)
LINE Corporation
JJUG CCC 2018 Fall (2018/Dec/15)
44
しゃべくり どのJDKつかうべきなの︖
Oracle OpenJDK (jdk.java.net)
AdoptOpenJDK
Amazon Corretto (AWS OpenJDK)
Azul Zulu
OpenJDK + OpenJ9
45

Migration Guide from Java 8 to Java 11 #jjug