当前位置: 首页 > 知识库问答 >
问题:

在ForkJoinPool Java中找不到JAXB类

谭泉
2023-03-14

我使用jaxb进行解组,但当我使用ForkJoinPool execute()方法时,我会得到一个“java.log.ClassNotFoundException:com.sun.xml.internal.bind.v2.ContextFactory”,但我确信在我的运行时类路径中存在,因为当我不使用ForkJoinPool时,它会正常工作。。。你知道这方面的问题或解决方法吗?

我使用Java 11

我的代码:

ForkJoinPool commonPool = ForkJoinPool.commonPool();
        commonPool.execute(() -> {
            try {
                String messageFileContent = Files.readString(Paths.get(
                        this.getClass().getClassLoader().getResource("xml-to-process.xml").getPath()));

                JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
                Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
                // avoiding schema validation for more performance
                jaxbUnmarshaller.setSchema(null);
                UpdateWorkOrder updateWorkOrder = (UpdateWorkOrder) jaxbUnmarshaller.unmarshal(new StringReader(messageFileContent));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

这很奇怪不?在ForkJoinPool的execute()之外,正确执行了解析。

错误是:

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]
java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(Unknown Source)
at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source)
at java.base/java.util.concurrent.ForkJoinPool.scan(Unknown Source)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:92)
at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:125)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:230)

共有2个答案

龙嘉誉
2023-03-14

如果ForkJoinPool使用的ClassLoader与您的应用程序不同,尤其是如果您使用的是Tomcat等Web容器,则可能会发生这种情况。

您可以尝试为ForkJoinPool设置线程工厂,并在该工厂中,将所创建线程的上下文类加载器设置为正确的应用程序类加载器。

锺离声
2023-03-14

虽然NightShade的回答完全描述了这个问题,但让我补充一些细节。

Servlet API世界和并发世界非常不兼容:前者假设所有计算都是在同一个线程上完成的(ServletRequest#start Async是相对较新的添加)。因此,使用Servlet API的应用程序和库通常会将对象附加到当前Thread,例如:

  • 执行请求的线程将应用程序的类加载器附加为“上下文类加载器”,
  • Spring将一个RequestContextHolder连接到当前线程(作为线程本地线程),
  • Vaadin通过CurrentInstance连接许多对象

这意味着,每当您想要在另一个线程上执行某些操作时,都需要将所有这些对象复制到目标线程上。一种简单的方法是为可运行的(和可调用的)编写包装器

public class WrappedRunnable implements Runnable {

   private final ClassLoader ccl;
   ... // other objects
   private final Runnable    runnable;

   public static Runnable wrap(final Runnable runnable) {
      if (runnable instanceof WrappedRunnable) {
         return runnable;
      }
      return new WrappedRunnable(runnable);
   }

   public WrappedRunnable(final Runnable runnable) {
      this.ccl = Thread.currentThread().getContextClassLoader();
      ... // other objects
      this.runnable = runnable;
   }

   @Override
   public void run() {
      final ClassLoader oldCcl = Thread.currentThread().getContextClassLoader();
      ... // save the value of other objects
      try {
         Thread.currentThread().setContextClassLoader(ccl);
         ... // set the value of other objects
         runnable.run();
      } finally {
         Thread.currentThread().setContextClassLoader(oldCcl);
         // restore the value of other objects
      }
   }
}

您还可以编写自己的执行服务(实际上您正在使用ForkJoinPool作为执行服务)或ForkJoinPool,这将自动包装可运行的。

 类似资料:
  • 我在用给定的xsd验证对象时遇到问题。已从类生成xsd。 这里是例外消息 [org.xml.sax.SAXParseException:cvc elt.1:找不到元素“ACCESREFUSE”的声明。] 以下是XSD: 元素ACCESREFUSE是xml的根。 XML: 知道吗?谢谢

  • 我写了phpUnit测试。我使用以下命令运行它:

  • 问题内容: 我一直在为我班的编程工作。我正在使用NetBeans。我完成了项目,效果很好。当我尝试运行它时,出现一条消息“找不到主类”。这是一些主要的代码: 我之前发布了此内容,但遇到了一些问题。我已经固定了其他人,现在只剩下这一个了。任何建议将不胜感激。 问题答案: 在项目浏览器中右键单击您的项目 点击属性 点击运行 确保您的主类是您想要成为切入点的主类。(确保使用完全限定的名称,即mypack

  • 我一直在做编程课的作业。我正在使用NetBeans。我完成了我的项目,它工作得很好。当我尝试运行它时,我收到一条消息,上面写着“找不到主类”。下面是一些主要的代码: 我以前发过这个,但有几个问题。我已经修好了其他的,现在只剩下这一个了。任何建议都将不胜感激。

  • 问题内容: 我有一个问题:nodemon不能运行npm脚本(例如), 但是如果在npm脚本之外的命令行上调用nodemon ,则nodemon会正常运行。 在npm脚本中如何调用它: 运行npm start脚本时: 我一直在寻找解决方案,但没有找到解决方案。 问题答案: 您可以通过添加以下内容来解决此问题: 在中不存在时会发生问题。 已添加,因为仅在开发期间才需要。

  • 问题内容: 我想使用 注释消除。我在网上找到了一些教程,我注意到这个注释来自软件包;但是当我导入它时,会生成一个编译错误:找不到符号 问题答案: 您需要包括一个存在该类的罐子。您可以在这里找到它 如果使用Maven,则可以添加以下依赖项声明: 对于Gradle: