Java 8 から Java 17 への移行メモ
私が携わっているOSS「Personium」のJava 8からの移行に係るトラブルに対しての対処を書いていきます。Personiumでは Java 8 → Java 11 → Java 17 というステップで移行を進めていく方針になっていて、今回は「Java 11 → Java 17」を行った際のメモです。よって「Java 8 → Java 11」で取り切れなかった不具合を含んでいる可能性も多分にありますのでご了承ください。
目次
- 目次
- Unsupported class file major version 61
- java.lang.reflect.InaccessibleObjectException
- It is forbidden to use algorithm ... 問題
- Jerseyのバージョンが古すぎる
- 終わりに
Unsupported class file major version 61
こんなエラーが出まくりました。
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 61 at org.jacoco.agent.rt.internal_1f1cc91.asm.ClassReader.<init>(ClassReader.java:184) at org.jacoco.agent.rt.internal_1f1cc91.asm.ClassReader.<init>(ClassReader.java:166) at org.jacoco.agent.rt.internal_1f1cc91.asm.ClassReader.<init>(ClassReader.java:152) at org.jacoco.agent.rt.internal_1f1cc91.core.internal.instr.InstrSupport.classReaderFor(InstrSupport.java:247) at org.jacoco.agent.rt.internal_1f1cc91.core.instr.Instrumenter.instrument(Instrumenter.java:86) at org.jacoco.agent.rt.internal_1f1cc91.core.instr.Instrumenter.instrument(Instrumenter.java:118)
上記は jacoco のバージョンが低い時に出たエラーなんですが、surefireのバージョンが低いことでも同様のエラーが発生しました。
というわけで、こちらの問題に対しては pom.xml
に Java 17 対応の jacoco, surefire のバージョンを記載してあげることで解決しました。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin>
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.7</version> </plugin>
(バージョンは一例です。)
java.lang.reflect.InaccessibleObjectException
こういうやつです。
java.lang.reflect.InaccessibleObjectException: Unable to make field protected volatile java.io.InputStream java.io.FilterInputStream.in accessible: module java.base does not "opens java.io" to unnamed module @hogehoge
どうも調べるとJava 17ではより高位なAPIがあるので、今までのローレベルなAPIは叩くなよという例外だそうです。
とはいっても、テストではゴリゴリそのAPIを使ってしまっているみたいで仕方ないのでテスト時オプションで例外的に許可してあげます。以下のように surefire の実行時引数に --add-opens
で必要なパッケージを列挙します。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <argLine> --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED </argLine> </configuration> </plugin>
文法的なものはドキュメント(Java Platform, Standard Edition Oracle JDK 9移行ガイド, リリース9)を参照していただくとして、例外の書式が以下だったとすると、
module <MODULE> does not "opens <PACKAGE>" to <TARGET_MODULE>
以下のように書けば素直に消えてくれるはずです。(TARGET_MODULEがunnamed moduleだった場合)
--add-opens=<MODULE>/<PACKAGE>=ALL-UNNAMED
ただこの、java.util
java.util.regex
java.util.zip
など複数パッケージに対して行う必要がある場合は以下のように愚直に書いていくしか無さそうでした(やり方あったら教えてください)。
--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.regex=ALL-UNNAMED --add-opens=java.base/java.util.zip=ALL-UNNAMED
コレ、1件解決したら次の1件、といった感じで芋づる式に出てくるので根気よく対処しましょう。ゆくゆくは根本対処を何かしたいところ・・・
It is forbidden to use algorithm ... 問題
SHA-1使ってたコードが軒並み動かなくなった問題です。
It is forbidden to use algorithm http://www.w3.org/2000/09/xmldsig#rsa-sha1 when secure validation is enabled
こちらは別記事にしたのでそちらをどうぞ。
Jerseyのバージョンが古すぎる
今まで Jersey 1.10とかいう化石のようなものを使っていたので、以下のようなエラーが出てしまっていました。
java.lang.IllegalArgumentException at jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:170) at jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:153) at jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:424)
というわけで一気に2系の2.36まであげました。
1から2への移行ということで、Jersey Test Frameworkの仕様も変わっていましたが、Grizzly + Servlet を使ったテストを実装するにあたって以下のサイトがとても参考になりました。
終わりに
以上が、PersoniumをJDK17に移行させるにあたって詰まった主な内容でした。どなたかの参考になれば幸いです。