Java parallelStream()导致JAXB-API出现ClassNotFoundException
在我们的应用程序中,有时会出现以下异常:Java parallelStream()导致JAXB-API出现ClassNotFoundException,java,jaxb,classloader,java-11,Java,Jaxb,Classloader,Java 11,在我们的应用程序中,有时会出现以下异常: javax.xml.bind.JAXBException:在模块路径或类路径上未找到JAXB-API的实现。 -除此之外: [java.lang.ClassNotFoundException:com.sun.xml.internal.bind.v2.ContextFactory] 我们已经发现,只有使用Collection.parallelStream()时才会发生这种情况,但如果使用Collection.stream(),则不会发生这种情况 我们看到
javax.xml.bind.JAXBException:在模块路径或类路径上未找到JAXB-API的实现。
-除此之外:
[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依赖项:
javax.xml.bind
jaxb api
2.3.1
org.glassfish.jaxb
jaxb运行时
2.3.1
javax.activation
激活
1.1.1
你知道会出什么问题吗?
AppClassLoader
怎么可能不知道我们的依赖关系呢?我遇到了类似的问题,我在org.apache.xerces.parsers.SAXParser
中得到了ClassNotFoundException。我已经删除/排除了对xercesImpl
、XMLAPI
、xmlbeans
、xmlschema core
的依赖关系,问题得到了解决,尽管我不知道为什么以及它是如何工作的。促使我删除这些jar的是XMLReaderFactory,它出现在jdk8
和xmlapi
中,我们有不同的体验。问题是tomcat的类加载器与每一个war不同(我认为我们在spring boot应用程序中看到了类似的东西;void main与application runner不同)
不管是哪种方式,问题在于“引导”类加载器无法访问应用程序中的JAR,因此没有jaxb。因此,如果您曾经从StreamXX.parallel()
或ForkJoinPool.commonThreadPool()
启动线程(如ForkJoinPoolThread
),那么这些线程将来自引导类加载器,而不是应用程序的类加载器。。因此,如果您的后台任务第一次加载JAXB,它们将运行getClass().getContextClassLoader().getResourceAsStream(“xxxx”)
,并且找不到资源
我们的解决方案是在显式线程池中启动所有后台任务,并拥有显式线程池工厂。。线程池工厂从调用线程(由war或spring启动上下文初始化的线程)捕获类加载器。这个类加载器将有jaxb和朋友。。因此,现在从这个线程池工厂启动的每个线程都有一个显式的thr.setContextClassLoader(globalCL)代码>
问题已解决(通过黑客)该类
以前在rt.jar
文件中提供,直到Java8
,然后从jdk
中删除
可能原因:您的应用程序使用了一些库,这些库使用了一些旧库,它们需要Java8
,其中包含xml.bind
,它从JDK11
中删除
解决方法:您只需从jdk8
复制文件/usr/lib/jvm/jre-1.8.0-openjdk/lib/rt.jar
,对其内容稍加修剪,只保存com.sun.xml.internal.bind.
包。然后将这个jar
放到您的tomcat/lib
文件夹中。您正在从某处加载旧版本的JAXB。在Java 11中,上下文工厂应该是:
com.sun.xml.bind.v2.ContextFactory
而不是
com.sun.xml.internal.bind.v2.ContextFactory
尝试执行以下操作:
将激活包升级到1.2。我不确定这和它有什么关系,但由于您使用的是Java11,我建议您使用Activation1.2
而不是插入jaxB的glassfish实现。使用以下依赖项:
javax.xml.bind
jaxb api
2.3.0
com.sun.xml.bind
jaxb内核
2.3.0
com.sun.xml.bind
jaxb impl
2.3.0
或交替地
jakarta.xml.bind
jakarta.xml.bind-api
2.3.3
如果这仍然不起作用,请回到我写给你的第一封信:
正确的上下文工厂是:
com.sun.xml.bind.v2.ContextFactory
某个地方加载了一个旧的vesion。行为的变化是在JDK9中引入的:(由于)
另见