GMOアドマーケティングのT.Nです。
2018年7月に、弊社のプロジェクトのJavaのバージョンを、
Java 8からJava 10にアップグレードしました。
2018年9月にJava 11がリリースされるので、
そのタイミングでJava 8からJava 11にアップグレードするというプロジェクトが多いかもしれませんが、弊社では10.0.2がリリースされたタイミングでアップグレードすることにしました。
今回は、アップグレードの際に行なったことをまとめます。
行なったこと一覧
- Jettyのバージョンアップ
- lombokのバージョンアップ
- JVMオプションの変更
- Gradleのバージョンアップ
- build.gradleのsourceCompatibilityの変更
- jsvcのバージョンアップ
- jdepsの実行
- jdeprscanの実行
- IntelliJの設定の変更
- CircleCIの設定の変更
Jettyのバージョンアップ
Jettyのバージョンを以下のようにアップグレードしました。
変更前 9.4.5.v20170502
変更後 9.4.11.v20180605
Jetty 9.4.7でearly JDK 9がサポートされるようになったらしいので、
9.4.5から最新の9.4.11にバージョンアップしました。
JettyのJavaのサポートについては、以下のページを参考にしました。
https://dev.eclipse.org/mhonarc/lists/jetty-announce/msg00111.html
lombokのバージョンアップ
lombokの使用箇所でコンパイルエラーが出たので、
lombokのバージョンを以下のようにアップグレードしました。
変更前 1.18.0
変更後 1.16.20
JVMオプションの変更
Java 9から使用できなくなったJVMオプションがあるので、いくつか変更を行いました。
変更前
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=10k
変更後
-Xlog:gc*:file=$LOG_DIR/gc_%p_%t.log::filecount=5,filesize=10k:time
変更前のオプションをJava 9以降のものに対応させると、
変更後に記載した内容のようになりますが、
実際には少し手を加えて、以下のような設定を使用することにしました。
実際の設定
-Xlog:gc*=info:file=$LOG_DIR/gc_%p_%t.log:time,uptime,level,tags:filecount=5,filesize=10k
設定方法については、以下のページが参考になります。
JEP 158: Unified JVM Logging
Gradleのバージョンアップ
弊社ではJavaのビルドにGradleを使用しているので、
Gradleのバージョンアップを行いました。
変更前 4.0.1
変更後 4.5.1
以下のページに、Gradle 4.2.1からJava 9がサポートされるようになったことが記載されています。
https://blog.gradle.org/java-9-support-update
build.gradleのsourceCompatibilityの変更
Gradleのビルドスクリプトのbuild.gradleで、
sourceCompatibilityを変更しました。
変更前 1.8
変更後 10
jsvcのバージョンアップ
弊社のプロジェクトで、jsvcでプログラムを実行している機能がありますが、
古いバージョンのjsvcでは起動ができなかったので、
jsvcのバージョンアップも行いました。
変更前 1.0.15
変更後 1.1.0
ちなみに、jsvcは、JavaのアプリケーションをUNIX系OSでデーモンとして実行するためのものです。
詳細は以下のページに記載されています。
https://commons.apache.org/proper/commons-daemon/jsvc.html
jdepsの実行
jdepsはクラスの依存関係を調査するためのコマンドです。
-jdkinternalsというオプションをつけて実行すると、JDKの内部APIへの依存を調査できます。
Java 9の新機能のmoduleを使用すると、JDKの内部APIにはアクセスできなくなります。
弊社のプロジェクトでは現在moduleを使用していないので、
内部APIへの依存があっても、問題はありませんが、
将来のことを考慮して、今回のアップグレード対応でもjdepsでの調査行いました。
結果として、以下の内部APIへの依存が見つかりましたが、今回は問題なしとしました。
1 2 3 4 |
JDK内部API 修正候補 -------- ---- sun.misc.Unsafe See http://openjdk.java.net/jeps/260 sun.reflect.Reflection Use java.lang.StackWalker @since 9 |
jdeprscanの実行
jdeprscanは非推奨メソッドが使用されているかを調査するためのコマンドです。
実行すると、以下のように非推奨メソッドの使用箇所が出力されます。
1 2 3 4 |
class com/google/common/io/FileBackedOutputStream$1が非推奨メソッドjava/lang/Object::finalize()Vをオーバーライドしています class com/google/common/reflect/Elementが非推奨メソッドjava/lang/reflect/AccessibleObject::isAccessible()Zを使用しています class com/google/common/reflect/Elementが非推奨メソッドjava/lang/reflect/AccessibleObject::isAccessible()Zをオーバーライドしています class com/google/common/util/concurrent/AtomicDoubleArrayが非推奨メソッドjava/util/concurrent/atomic/AtomicLongArray::weakCompareAndSet(IJJ)Zを使用しています |
調査の結果、使用しているライブラリーが非推奨メソッドを使用していることが分かりました。
非推奨メソッドの使用箇所を全てなくしたいところですが、困難であるため、
当面は、アプリケーションのコードでは非推奨メソッドを使用しないようにし、
ライブラリーでの使用については、本当に削除されてしまわないうちは、
問題なしとすることにしました。
IntelliJの設定の変更
File > Project Structureで、各項目のJavaのバージョンを10に指定しました。
また、JUnit実行時のVM optionsに、-Djdk.attach.allowAttachSelfを追加しました。
弊社のテストクラスでは、jmockitを使用していますが、
jmockitを使用しているテストクラスを実行すると、以下のようなエラーメッセージが出ます。
1 |
java.lang.IllegalStateException: Running on JDK 9 requires -javaagent:/jmockit-1.n.jar or -Djdk.attach.allowAttachSelf |
そのため、JUnit実行時のVM optionsに、-Djdk.attach.allowAttachSelfを追加しました。
-Djdk.attach.allowAttachSelfについては、以下のページが参考になります。
Attach API cannot be used to attach to the current VM by default
CircleCIの設定の変更
使用するDocker Imageを変更しました。
変更前 circleci/openjdk:8-jdk-browsers
変更後 circleci/openjdk:10.0.2-jdk-browsers
最後に
Java 8とJava 9の間で変更された点が多いので、
今回のJava 8からのアップグレードでは、対応が必要な部分が多かったです。
今回ブログに書いた内容は、Java 10へのアップグレードに関するものですが、
Java 8からJava 11にアップグレードする場合にも参考にできると思います。
2018年9月にはJava 11がリリースされるので、
Java 10からJava 11へのアップグレードについても、
こちらのブログで情報を発信できると良いです。