web-dev-qa-db-ja.com

PrailleStream()JAXB-APIでClassNotFoundExceptionを引き起こす

私たちのアプリケーションでは、次の例外が発生します。

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]

これがCollection.parallelStream()を使用しているがCollection.stream()を使用していない場合にのみ起こることをすでにわかりました。

JAXBがクラスをロードするためのThread.currentThread().getContextClassLoader()を使用することを見ました。また、parallelStream()を使用する場合、コマンドを実行するためのスレッドは異なるクラスローダを使用しています。時々それはorg.Apache.catalina.loader.WebappClassLoaderであり、時にはjdk.internal.loader.ClassLoaders.AppClassLoaderです。

そして、AppClassLoaderがJAXBの依存関係について知らないのは、WebappClassLoaderが行います。

Java 11と次のMavenの依存関係を使用しています。

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>

何が間違っている可能性がありますか?どうやってAppClassLoaderは私たちの依存関係について知らないことになりますか?

20
Ethan Leroy

私たちは異なる経験をしました。この問題は、Tomcatが各戦争よりも異なるクラスローダーを持っているということでした(私たちは春の起動アプリと似ている何かを見ています。void-mainがアプリケーションランナーのどちらにも異なり)。 「クラスローダーはあなたのアプリケーション内のjarsにアクセスすることはありません - そしてしたがってJAXBはありません。そのため、スレッドを起動したことがある場合(StreamXX.Parallel()またはForkjoinPool.commonthreadpool())、それらのスレッドはbootstrap ClassLoader、アプリケーションのクラスローダーではなく)からなります。バックグラウンドタスクがJAXBをロードするときには、getClass()が実行されます。getContextClassLoader()getResourceAsStream( "xxxx")とリソースが見つかりませんでした。私たちの解決策は明示的なスレッドプールですべてのバックグラウンドタスクを起動し、明示的なスレッドプールファクトリ..スレッドプールファクトリは、呼び出しスレッド(WARまたはSpring-Boot Contextによって初期化されたもの)からクラスローダーをキャプチャします。このクラスローダーはJAXBと友達を持ちます。このスレッドプールファクトリには、明示的なTHR.SetContextClassLoader(GlobalCL)があります。...問題解決(ハックを介して)

1
M. Maraist

このクラスcom.Sun.xml.internal.bind.v2.ContextFactoryは、ファイルrt.jarまでJava 8に以前に利用でき、jdkからトリミングされました。


考えられる原因:あなたのアプリケーションはいくつかの古いライブラリを使用します。これはいくつかの古いライブラリを使用します。これはJava 8を含むxml.bindを含むjdk 11からトリミングされます。


回避策:/usr/lib/jvm/jre-1.8.0-openjdk/lib/rt.jarからファイルjdk 8を単にコピーすることは、その内容を少しトリミングして、com.Sun.xml.internal.bind.*パッケージのみを保存することができます。その後、このjarTomcat/libフォルダに入れます。

0
user11141611