Error occurred during initialization of boot layer

2019年7月23日

というエラーが発生した。

ケース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プラグインのクラスパス設定を見てみる必要がある。