[〜#〜] tldr [〜#〜]:On Java 9/10、TomcatのWebアプリ参照実装がクラスパスに存在していても、JAXBにアクセスできません。
Edit:いいえ、これは Java.lang.NoClassDefFoundErrorの解決方法:javax/xml/bind/JAXBException in = Java 9 -私が試したことセクションでわかるように、私はすでに提案された解決策を試しました。
Tomcatで実行され、JAXBに依存するWebアプリがあります。 Java 9への移行中に、 通常の依存関係としてのJAXB参照実装 の追加を選択しました。
IDE Tomcatが埋め込まれている) からアプリを起動するとすべてが機能しましたが、実際のTomcatインスタンスで実行すると、このエラーが発生します。
Caused by: Java.lang.RuntimeException: javax.xml.bind.JAXBException:
Implementation of JAXB-API has not been found on module path or classpath.
- with linked exception:
[Java.lang.ClassNotFoundException: com.Sun.xml.internal.bind.v2.ContextFactory]
at [... our-code ...]
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.Java:278) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.find(ContextFinder.Java:421) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.Java:721) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.Java:662) ~[jaxb-api-2.3.0.jar:2.3.0]
at [... our-code ...]
Caused by: Java.lang.ClassNotFoundException: com.Sun.xml.internal.bind.v2.ContextFactory
at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.Java:582) ~[?:?]
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.Java:190) ~[?:?]
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:499) ~[?:?]
at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.Java:122) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.Java:155) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.Java:276) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.find(ContextFinder.Java:421) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.Java:721) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.Java:662) ~[jaxb-api-2.3.0.jar:2.3.0]
at [... our-code ...]
注意:
JAXB-APIの実装がモジュールパスまたはクラスパスに見つかりませんでした。
これらはwebapps/$app/WEB-INF/lib
の関連ファイルです:
jaxb-api-2.3.0.jar
jaxb-core-2.3.0.jar
jaxb-impl-2.3.0.jar
ここで何が起こっていますか?
CLASSPATH
へのJARの追加setenv.sh
にあるTomcatのクラスパスにJARを追加すると役立つかもしれません。
CLASSPATH=
.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar:
.../webapps/$app/WEB-INF/lib/jaxb-impl-2.3.0.jar:
.../webapps/$app/WEB-INF/lib/jaxb-core-2.3.0.jar:
.../webapps/$app/WEB-INF/lib/javax.activation-1.2.0.jar
いいえ:
Caused by: javax.xml.bind.JAXBException: ClassCastException: attempting to cast
jar:file:.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar!/javax/xml/bind/JAXBContext.class to
jar:file:.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar!/javax/xml/bind/JAXBContext.class.
Please make sure that you are specifying the proper ClassLoader.
at javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.Java:157) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.Java:300) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.Java:286) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.find(ContextFinder.Java:409) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.Java:721) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.Java:662) ~[jaxb-api-2.3.0.jar:2.3.0]
at de.disy.gis.webmapserver.factory.DefaultWmsRequestFactory.initializeCommandExtractor(DefaultWmsRequestFactory.Java:103) ~[cadenza-gis-webmapserver-7.7-SNAPSHOT.jar:7.6]
at de.disy.gis.webmapserver.factory.DefaultWmsRequestFactory.lambda$new$0(DefaultWmsRequestFactory.Java:87) ~[cadenza-gis-webmapserver-7.7-SNAPSHOT.jar:7.6]
これは明らかに同じクラスなので、明らかに2つのクラスローダーによってロードされています。 システムクラスローダーとアプリのクラスローダー が疑われるが、なぜJAXBContext
の読み込みがシステムクラスローダーに一度だけ委任されるのか?プログラムの実行中に、アプリのクラスローダーの委任動作が変更されるように見えます。
私は本当にJava.xml.bindを追加したくありませんが、とにかくこれをcatalina.sh
に追加して試してみました:
JDK_Java_OPTIONS="$JDK_Java_OPTIONS --add-modules=Java.xml.bind"
ただし、どちらも機能しません:
Caused by: Java.lang.ClassCastException:
Java.xml.bind/com.Sun.xml.internal.bind.v2.runtime.JAXBContextImpl
cannot be cast to com.Sun.xml.bind.v2.runtime.JAXBContextImpl
at [... our-code ...]
異なるクラスとスタックトレースは別として、これは以前に起こったことと一致しています。クラスJAXBContextImpl
がJava.xml.bind(システムクラスローダーである必要があります)ともう一度(私はJARからアプリのローダーによって仮定します)。
Tomcatのバグデータベースを検索 見つかった #62559 。それは同じエラーでしょうか?
lib
にJARを追加するTomcatユーザーメーリングリストでのアドバイス に従って、JAXB JARをTomcatのCATALINA_BASE/lib
ディレクトリに追加しましたが、アプリケーションのlibフォルダーと同じエラーが発生しました。
最初にいくつかのランダムな事実:
JAXBContext::newInstance
はJAXB実装を検索するときに スレッドのコンテキストクラスローダー を使用します-newInstance(Class...)
(提供されたクラスインスタンスのローダーを使用すると誤って考えるかもしれません)Java 8:
Java 9に入ります-ピアノの演奏が停止し、全員がスコッチを置きます:
解決策は、JAXBが適切なクラスローダーを使用するようにすることです。次の3つの方法を知っています。
Thread.getCurrentThread().setContextClassLoader(this.getClass().getClassLoader());
を呼び出しますが、それはあまり良い考えではありませんJAXBContext::newInstance
のパッケージ受け入れバリアントを使用します( Java EE 7 からのJavadoc)。これもクラスローダーを受け取り、正しいローダーを渡しますが、いくつかのリファクタリング3番目のオプションを使用し、JAXBContext::newInstance
のパッケージ受け入れバリアントに向けてリファクタリングしました。面倒な作業ですが、問題は修正されました。
ユーザーcurlals は重要な情報を提供しましたが、回答を削除しました。いくつかの編集を依頼したからではないことを願っています。すべてのクレジット/カルマはそれらに行く必要があります! @curlals:回答を復元および編集する場合、私はそれを受け入れ、賛成します。
以下とその依存関係を試してください。 最新バージョンのMavenリポジトリ を参照してください。
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.0.1</version>
</dependency>
また、Java Service Loader記述子も含まれています。 Java 9+でのJAXBの使用 を参照してください