java - 带有用于 javadoc doclet 的自定义 xml 序列化程序的 ClassNotFoundException

标签 java classloader javadoc woodstox

tl;dr; XmlOutputFactory 使用的类加载器提示找不到 Woodstox,即使 doclet 自己的类加载器可以找到它.

如果在 our sample project 中运行 javadoc 目标在我们将 xml 工厂设置为使用 Woodstox 序列化程序的地方,XmlOutputFactory 使用的类加载器提示找不到该文件,即使它可以在 doclet 中找到。

Constructing Javadoc information...
java.net.URLClassLoader@20fa23c1
Check that we can get hold of class: com.ctc.wstx.stax.WstxOutputFactory
Setting javax.xml.stream.XMLOutputFactory to com.ctc.wstx.stax.WstxOutputFactory
Trying to instantiate a new instance from XMLOutputFactory

...
[ERROR] Exit code: 4 - javadoc: error - fatal error encountered: javax.xml.stream.FactoryConfigurationError: Provider com.ctc.wstx.stax.WstxOutputFactory not found
[ERROR] javadoc: error - Please file a bug against the javadoc tool via the Java bug reporting page
[ERROR] (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com)
[ERROR] for duplicates. Include error messages and the following diagnostic in your report. Thank you.
[ERROR] javax.xml.stream.FactoryConfigurationError: Provider com.ctc.wstx.stax.WstxOutputFactory not found
[ERROR]     at java.xml/javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:196)
[ERROR]     at java.xml/javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:148)
[ERROR]     at java.xml/javax.xml.stream.FactoryFinder.find(FactoryFinder.java:260)
[ERROR]     at java.xml/javax.xml.stream.FactoryFinder.find(FactoryFinder.java:222)
[ERROR]     at java.xml/javax.xml.stream.XMLOutputFactory.newInstance(XMLOutputFactory.java:138)
[ERROR]     at docs.JacksonWriter.write(JacksonWriter.java:161)
[ERROR]     at docs.TestSheetDoclet.run(TestSheetDoclet.java:98)
[ERROR]     at jdk.javadoc/jdk.javadoc.internal.tool.Start.parseAndExecute(Start.java:588)
[ERROR]     at jdk.javadoc/jdk.javadoc.internal.tool.Start.begin(Start.java:432)
[ERROR]     at jdk.javadoc/jdk.javadoc.internal.tool.Start.begin(Start.java:345)
[ERROR]     at jdk.javadoc/jdk.javadoc.internal.tool.Main.execute(Main.java:63)
[ERROR]     at jdk.javadoc/jdk.javadoc.internal.tool.Main.main(Main.java:52)
[ERROR] Caused by: java.lang.ClassNotFoundException: com/ctc/wstx/stax/WstxOutputFactory

所以虽然我们的 JacksonWriter clearly finds the class (查看输出),似乎 XmlOutputFactory 没有,表明它有某种其他类加载器看不到提供的类路径。

你可以看到在target/site/testapidocs/options中使用的完整类路径:

    -classpath
    '/home/myuser/dev/tmp/server-javadoc-repro/target/classes:/home/myuser/dev/tmp/server-javadoc-repro/target/test-classes:/home/myuser/.m2/repository/org/jetbrains/annotations/17.0.0/annotations-17.0.0.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.9.7/jackson-module-parameter-names-2.9.7.jar:/home/myuser/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/home/myuser/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.7/jackson-databind-2.9.7.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/home/myuser/.m2/repository/org/assertj/assertj-core/3.11.1/assertj-core-3.11.1.jar:/home/myuser/.m2/repository/org/codehaus/woodstox/stax2-api/3.1.4/stax2-api-3.1.4.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/dataformat/jackson-dataformat-xml/2.9.7/jackson-dataformat-xml-2.9.7.jar:/home/myuser/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/home/myuser/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar:/home/myuser/.m2/repository/junit/junit/4.12/junit-4.12.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.7/jackson-core-2.9.7.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.9.7/jackson-module-jaxb-annotations-2.9.7.jar:/home/myuser/.m2/repository/com/fasterxml/woodstox/woodstox-core/5.0.3/woodstox-core-5.0.3.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/dataformat/jackson-dataformat-xml/2.9.7/jackson-dataformat-xml-2.9.7.jar:/home/myuser/.m2/repository/com/fasterxml/woodstox/woodstox-core/5.0.3/woodstox-core-5.0.3.jar'
    -doclet
    'docs.TestSheetDoclet'
    -docletpath
    '/home/myuser/dev/tmp/server-javadoc-repro/target/acme-server-with-javadoc-issues-0.0.1-SNAPSHOT.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.7/jackson-databind-2.9.7.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.7/jackson-core-2.9.7.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.9.7/jackson-module-parameter-names-2.9.7.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/dataformat/jackson-dataformat-xml/2.9.7/jackson-dataformat-xml-2.9.7.jar:/home/myuser/.m2/repository/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.9.7/jackson-module-jaxb-annotations-2.9.7.jar:/home/myuser/.m2/repository/org/codehaus/woodstox/stax2-api/3.1.4/stax2-api-3.1.4.jar:/home/myuser/.m2/repository/com/fasterxml/woodstox/woodstox-core/5.0.3/woodstox-core-5.0.3.jar:/home/myuser/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/home/myuser/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/home/myuser/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar:/home/myuser/.m2/repository/org/jetbrains/annotations/17.0.0/annotations-17.0.0.jar:/home/myuser/.m2/repository/com/fasterxml/woodstox/woodstox-core/5.0.3/woodstox-core-5.0.3.jar:/home/myuser/.m2/repository/org/codehaus/woodstox/stax2-api/3.1.4/stax2-api-3.1.4.jar'
    -encoding
    'UTF-8'
    -protected
    -sourcepath
    '/home/myuser/dev/tmp/server-javadoc-repro/src/test/java:/home/myuser/dev/tmp/server-javadoc-repro/target/generated-test-sources/test-annotations'

如何重现

git clone https://github.com/fatso83/server-javadoc-repro
cd server-javadoc-repro
mvn install org.apache.maven.plugins:maven-javadoc-plugin:3.0.1:test-javadoc

最佳答案

javax.xml.datatype.FactoryFinder.getProviderClass()(根据 OpenJDK 12+33)的文档指出:

    /**
     * Attempt to load a class using the class loader supplied. If that fails
     * and fall back is enabled, the current (i.e. bootstrap) class loader is
     * tried.
     *
     * If the class loader supplied is <code>null</code>, first try using the
     * context class loader followed by the current (i.e. bootstrap) class
     * loader.
     *
     * Use bootstrap classLoader if cl = null and useBSClsLoader is true
     */

因此,如果您在调用 XMLOutputFactory.newInstance() 之前重写线程上下文类加载器,您应该很好:

Thread.currentThread().setContextClassLoader(WstxOutputFactory.class.getClassLoader());
final var xmlOutputFactory = XMLOutputFactory.newInstance();

JAXP 有许多不同的方法来配置在运行时使用哪个 JAXP 实现(或“提供者”),但最简单的是将系统属性 javax.xml.stream.XMLOutputFactory 设置为您要使用的实现类的名称,在您的情况下为 com.ctc.wstx.stax.WstxOutputFactory:

System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory");

关于java - 带有用于 javadoc doclet 的自定义 xml 序列化程序的 ClassNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55628490/

相关文章:

java - 使用 LWJGL 小程序访问资源

java - 加载jar附带的JNA库

java - 在 Scala 中实现多级 Java 接口(interface)

java - 什么是并发语言?

java - 核心计数任务 CompletableFuture 比 parallelStream 慢

java - 通过 URLClassLoader 使用文件作为资源

java - 如何查看 Java 10 Javadocs(在 Eclipse 中)

android-studio - 如何在 Android Studio 中启用 JAVADOC View

java - 如何修复 javadoc :fix 中的 "MavenInvocationException"

java - Android:RESTful JDBC 代理。性能和安全性