Java 10へのアップグレード

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への依存が見つかりましたが、今回は問題なしとしました。

jdeprscanの実行

jdeprscanは非推奨メソッドが使用されているかを調査するためのコマンドです。
実行すると、以下のように非推奨メソッドの使用箇所が出力されます。

調査の結果、使用しているライブラリーが非推奨メソッドを使用していることが分かりました。
非推奨メソッドの使用箇所を全てなくしたいところですが、困難であるため、
当面は、アプリケーションのコードでは非推奨メソッドを使用しないようにし、
ライブラリーでの使用については、本当に削除されてしまわないうちは、
問題なしとすることにしました。

IntelliJの設定の変更

File > Project Structureで、各項目のJavaのバージョンを10に指定しました。
また、JUnit実行時のVM optionsに、-Djdk.attach.allowAttachSelfを追加しました。

弊社のテストクラスでは、jmockitを使用していますが、
jmockitを使用しているテストクラスを実行すると、以下のようなエラーメッセージが出ます。

そのため、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へのアップグレードについても、
こちらのブログで情報を発信できると良いです。