Error occurred during initialization of boot layer
というエラーが発生した。
ケース1
エラー
Eclipse上で実行させたのだが、Eclipseに限らず、何らかのモジュール関連エラーがあるときに発生するようだ。
Error occurred during initialization of boot layer
java.lang.module.ResolutionException: Modules jsr305 and java.annotation export package javax.annotation to module hk2.locator
要するに、Java9では複数のモジュールに同じパッケージの存在は許されないのだが、javax.annotationというパッケージが、jsr305とjava.annotationという2つのモジュールにそれぞれ存在し、これをhk2.locatorモジュールが使用しているということのようだ。
原因
自作のライブラリの方に原因があった。こちらは、モジュールとして構成しておらず、複数モジュールに同じパッケージが存在しており、その原因はJerseyだった。
以下のようにJerseyの依存するjarを排除。
/* ひどいことにJerseyのライブラリは基本的なパッケージを再定義したjarファイルに
* 依存している。これはOSGiに対応するためだというのだが、モジュールシステムでは
* 複数のモジュールに同じパッケージ名称は許されない。また、OSGiの機能は使用しない
* ので、これらは排除する。
* https://stackoverflow.com/questions/25212944/why-does-hk2-repackage-everything
*/
configurations {
implementation.exclude module:'jakarta.inject' // defines javax.inject
implementation.exclude module:'jsr305' // defines javax.annotation
implementation.exclude module:'aopalliance-repackaged' // defines org.aopalliance.aop
}
dependencies {
/* JAX-RS、Jersey、Jacksonを使う
* configurationsのexcludeコメントを参照のこと。
* https://www.gwtcenter.com/using-restygwt-1
*/
implementation group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.1.1'
implementation group:'org.glassfish.jersey.containers', name: 'jersey-container-servlet', version: '2.29'
implementation group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: '2.29'
implementation group: 'com.fasterxml.jackson.jaxrs', name: 'jackson-jaxrs-json-provider', version: '2.9.9'
implementation group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.29'
(その他の依存)
このexcludeが無いとどうなるかだが、やはり同じエラーになる。
Error occurred during initialization of boot layer
java.lang.module.ResolutionException: Modules java.annotation and jsr305 export package javax.annotation to module j2objc.annotations
教訓
可能な限りモジュールとして構成しておくべき。モジュールとして構成すれば、少なくともあとあとパッケージの重複に悩まされずに済む。
ケース2
同じくEclipseでのエラーだ。なぜかGrladleでのコンパイルはうまく行くのだが、Eclipseで実行しようとすると下記のエラーになる。
エラー
Error occurred during initialization of boot layer
java.lang.module.FindException: Unable to derive module descriptor for C:\Users\admin\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.9.9\8b717e1bc24a642cee070ae3860f04eb20c92779\jackson-databind-2.9.9-sources.jar
Caused by: java.lang.module.InvalidModuleDescriptorException: Provider class com.fasterxml.jackson.databind.ObjectMapper not in module
原因
おそらくはEclipseのバグと思ったのだが、実はGradleのEclipseプラグインの仕業かもしれない。Eclipseのクラスパスを設定しているのが、これだからだ。
エラー内容を見てみると、jackson-databind-2.9.9-sources.jarのmodule descriptorを取得できないと言っており、たしかにEclipseのクラスパスを見てみると、どういうわけか、このソースjarがクラスパスに入っている。
つまり、ソースがバイナリjarとして扱われてしまっているという明らかなバグだ。
この原因なのだが、全く無関係なjarファイルの依存の中にjackson-databindの古いバージョンがあるせいらしい。このjarファイルからjackson-databindを除去したら正常になったのだが、しかし何にしてもEclipseのバグであることは間違いない。
教訓
ともあれ、GradleのEclipseプラグインのクラスパス設定を見てみる必要がある。