java - parallelStream() 使用 JAXB-API 导致 ClassNotFoundException

标签 java jaxb classloader java-11

在我们的应用程序中,我们有时会遇到以下异常:

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 怎么会不知道我们的依赖关系?

最佳答案

我们有不同的经历。问题是 tomcat 与每次 war 都有不同的类加载器(我认为我们在 spring boot 应用程序中看到了类似的东西;void-main 与 application-runner 不同)。

无论哪种方式,问题是“bootstrap”类加载器无法访问应用程序中的 jars - 因此没有 jaxb。因此,如果您曾经启动一个线程(例如 StreamXX.parallel()ForkJoinPool.commonThreadPool() 中的 ForkJoinPoolThread),那么这些线程将来自引导类加载器,而不是您的应用程序的类加载器。因此,如果您的后台任务第一次加载 JAXB,它们将运行 getClass().getContextClassLoader().getResourceAsStream("xxxx") 并且不会找到资源。

我们的解决方案是在显式线程池中启动所有后台任务,并有一个显式线程池工厂。线程池工厂从调用线程(由 war 或 spring 初始化的线程)捕获类加载器-引导上下文)。这个类加载器将有 jaxb 和 friend ..所以现在从这个线程池工厂启动的每个线程都有一个显式的 thr.setContextClassLoader(globalCL);....

问题已解决(通过 hack)

关于java - parallelStream() 使用 JAXB-API 导致 ClassNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55452778/

相关文章:

java - 将 Java ENUM 转换为 XML

java - 解码 JAXB 的 WebLogic 12c 迁移问题

java - 序列化多层 XML 元素

java - 如何避免在类初始化之前访问静态字段引起的问题?

java - 什么时候应该初始化类 - 在加载时还是在第一次使用时?

java - 一个 Spring 应用程序中的多个 WebSecurityConfig

java - HashMap : sorting key into alphabetical order with it's mapped values

Java 或任何其他语言 : Which method/class invoked mine?

java - EmbeddedChannel 和 ChannelActive

java - Maven 构建显示编译错误,但 Eclipse 没有