关于jaxb:如何解决java.lang.NoClassDefFoundError:Java 9中的javax / xml / bind / JAXBException

How to resolve java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException in Java 9

我有一些代码使用JAXB API类,它们是作为Java 6/7/8中JDK的一部分提供的。 当我使用Java 9运行相同的代码时,在运行时我得到错误,指示无法找到JAXB类。

自Java 6以来,JAXB类已作为JDK的一部分提供,为什么Java 9不再能够找到这些类?


JAXB API被认为是Java EE API,因此不再包含在Java SE 9中的默认类路径中。在Java 11中,它们完全从JDK中删除。

Java 9引入了模块的概念,默认情况下,java.se聚合模块在类路径(或更确切地说,模块路径)上可用。顾名思义,java.se聚合模块不包含传统上与Java 6/7/8捆绑在一起的Java EE API。

幸运的是,JDK 6/7/8中提供的这些Java EE API仍然在JDK中,但它们默认情况下不在类路径上。以下模块中提供了额外的Java EE API:

1
2
3
4
5
6
java.activation
java.corba
java.transaction
java.xml.bind  << This one contains the JAXB APIs
java.xml.ws
java.xml.ws.annotation

快速而肮脏的解决方案:(仅限JDK 9/10)
要在运行时使JAXB API可用,请指定以下命令行选项:
--add-modules java.xml.bind

但我仍然需要这个与Java 8一起工作!
如果您尝试使用较旧的JDK指定--add-modules,它将会爆炸,因为它是一个无法识别的选项。我建议两种选择之一:

  • 您可以使用JDK_JAVA_OPTIONS环境变量设置任何仅Java 9+选项。该环境变量由java启动程序自动读取,用于Java 9+。
  • 您可以添加-XX:+IgnoreUnrecognizedVMOptions以使JVM静默忽略无法识别的选项,而不是炸毁。但要小心!您使用的任何其他命令行参数将不再由JVM验证。此选项适用于Oracle / OpenJDK以及IBM JDK(从JDK 8sr4开始)
  • 替代快速解决方案:(仅限JDK 9/10)
    请注意,您可以通过指定--add-modules java.se.ee选项在运行时使所有上述Java EE模块可用。 java.se.ee模块是一个聚合模块,包含java.se.ee以及上述Java EE API模块。

    适当的长期解决方案:(JDK 9及更高版本)

    上面列出的Java EE API模块都标记为@Deprecated(forRemoval=true),因为它们计划在Java 11中删除。因此--add-module方法将不再适用于Java 11开箱即用。

    您需要在Java 11和转发中执行的操作是在类路径或模块路径上包含您自己的Java EE API副本。例如,您可以将JAX-B API添加为maven依赖项,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <dependency>
        <groupId>javax.xml.bind</groupId>
        jaxb-api</artifactId>
        <version>2.2.11</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        jaxb-core</artifactId>
        <version>2.2.11</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        jaxb-impl</artifactId>
        <version>2.2.11</version>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        activation</artifactId>
        <version>1.1.1</version>
    </dependency>

    有关Java模块化的完整详细信息,请参阅JEP 261:模块系统

    对于Gradle或Android Studio开发人员:(JDK 9及更高版本)

    将以下依赖项添加到build.gradle文件中:

    1
    2
    3
    4
    5
    6
    7
    dependencies {
        // JAX-B dependencies for JDK 9+
        implementation"javax.xml.bind:jaxb-api:2.2.11"
        implementation"com.sun.xml.bind:jaxb-core:2.2.11"
        implementation"com.sun.xml.bind:jaxb-impl:2.2.11"
        implementation"javax.activation:activation:1.1.1"
    }


    在我的情况下(spring boot fat jar)我只是将以下内容添加到pom.xml中。

    1
    2
    3
    4
    5
    <dependency>
        <groupId>javax.xml.bind</groupId>
        jaxb-api</artifactId>
        <version>2.3.0</version>
    </dependency>


    在最近的JDK 9.0.1中,这些解决方案都不适用于我。

    我发现这个依赖项列表足以实现正常运行,因此您不需要显式指定--add-module(尽管它是在这些依赖项的pom中指定的)。您唯一需要的是指定此依赖项列表:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <dependencies>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            jaxb-runtime</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            activation</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>


    这对我有用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <dependency>
        <groupId>javax.xml.bind</groupId>
        jaxb-api</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        eclipselink</artifactId>
        <version>2.7.0</version>
    </dependency>

    更新

    正如@Jasper建议的那样,为了避免依赖整个EclipseLink库,你也可以依赖于EclipseLink MOXy:

    Maven的

    1
    2
    3
    4
    5
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        org.eclipse.persistence.moxy</artifactId>
        <version>2.7.3</version>
    </dependency>

    摇篮

    1
    compile group: 'org.eclipse.persistence', name: 'org.eclipse.persistence.moxy', version: '2.7.3'

    作为我的Java 8应用程序的依赖项,它生成一个* .jar,它可以由JRE 8或JRE 9运行,没有其他参数。

    此外,这需要在使用JAXB API之前在某处执行:

    1
    System.setProperty("javax.xml.bind.JAXBContextFactory","org.eclipse.persistence.jaxb.JAXBContextFactory");

    到目前为止工作得很好,作为一种解决方法。虽然看起来不是一个完美的解决方案......


    这是因为java版本,如果你使用jdk 9或更高版本,只需将它添加到你的pom

    1
    2
    3
    4
    5
    <dependency>
      <groupId>javax.xml.bind</groupId>
      jaxb-api</artifactId>
      <version>2.3.0</version>
    </dependency>


    在编译和运行时,添加开关--add-modules java.xml.bind

    1
    2
    3
    javac --add-modules java.xml.bind <java file name>

    java --add-modules java.xml.bind <class file>

    还可以在以下位置找到JDK 9模块的详细介绍:


    所有JDK的清洁解决方案> = 9

    您需要为构建添加两个依赖项

    • jaxb-api
    • 一个jaxb实现

    作为一个实现,我选择使用glassfish的参考实现来摆脱旧的com.sun类/库。
    因此,我添加了我的maven构建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <dependency>
      <groupId>javax.xml.bind</groupId>
      jaxb-api</artifactId>
      <version>2.3.1</version>
    </dependency>

    <dependency>
      <groupId>org.glassfish.jaxb</groupId>
      jaxb-runtime</artifactId>
      <version>2.3.1</version>
    </dependency>

    请注意,从版本2.3.1开始,您不再需要添加javax.activation。 (见https://github.com/eclipse-ee4j/jaxb-ri/issues/1222)


    为了解决这个问题,我在项目中导入了一些JAR文件:

    • javax.activation中-1.2.0.jar

    http://search.maven.org/remotecontent?filepath=com/sun/activation/javax.activation/1.2.0/javax.activation-1.2.0.jar

    • JAXB的API-2.3.0.jar

    http://search.maven.org/remotecontent?filepath=javax/xml/bind/jaxb-api/2.3.0/jaxb-api-2.3.0.jar

    • JAXB的核心2.3.0.jar

    http://search.maven.org/remotecontent?filepath=com/sun/xml/bind/jaxb-core/2.3.0/jaxb-core-2.3.0.jar

    • JAXB的IMPL-2.3.0.jar

    http://search.maven.org/remotecontent?filepath=com/sun/xml/bind/jaxb-impl/2.3.0/jaxb-impl-2.3.0.jar

  • 下载上述文件并将其复制到项目中的libs文件夹中
  • 在Java Build Path中添加导入的JAR文件

  • 您可以使用--add-modules=java.xml.bind JVM选项将xml绑定模块添加到JVM运行时环境。

    例如:java --add-modules=java.xml.bind XmlTestClass


    这对我有用。仅添加jaxb-api是不够的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
            <dependency>
                <groupId>javax.xml.bind</groupId>
                jaxb-api</artifactId>
                <version>${jaxb-api.version}</version>
            </dependency>
            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                jaxb-impl</artifactId>
                <version>${jaxb-api.version}</version>
            </dependency>
            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                jaxb-core</artifactId>
                <version>${jaxb-api.version}</version>
            </dependency>


    转到Build.gradle并为Java 9或Java 10添加以下依赖项。

    1
    2
    3
    4
    5
    6
    7
    8
    sourceCompatibility = 10 // You can also decrease your souce compatibility to 1.8

    //java 9+ does not have Jax B Dependents

        compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.0'
        compile group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.0'
        compile group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '2.3.0'
        compile group: 'javax.activation', name: 'activation', version: '1.1.1'

    对于Java Web Start Execution,我们可以使用Andy Guibert的建议:

    1
    2
    <j2se version="1.6+"
          java-vm-args="-XX:+IgnoreUnrecognizedVMOptions --add-modules=java.se.ee"/>

    注意--add-modules中的额外"="。请参阅此OpenJDK Ticket或Java平台标准版Oracle JDK 9迁移指南的"了解运行时访问警告"中的最后一个注释。


    2019年4月更新

    适用于JAXB版本的Changelong位于https://javaee.github.io/jaxb-v2/doc/user-guide/ch02.html

    摘录:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
        4.1. Changes between 2.3.0.1 and 2.4.0

             JAXB RI is now JPMS modularized:

                All modules have native module descriptor.

                Removed jaxb-core module, which caused split package issue on JPMS.

                RI binary bundle now has single jar per dependency instead of shaded fat jars.

                Removed runtime class weaving optimization.

        4.2. Changes between 2.3.0 and 2.3.0.1

              Removed legacy technology dependencies:

                com.sun.xml.bind:jaxb1-impl

                net.java.dev.msv:msv-core

                net.java.dev.msv:xsdlib

                com.sun.xml.bind.jaxb:isorelax

        4.3. Changes between 2.2.11 and 2.3.0

              Adopt Java SE 9:

                JAXB api can now be loaded as a module.

                JAXB RI is able to run on Java SE 9 from the classpath.

                Addes support for java.util.ServiceLoader mechanism.

                Security fixes

    权威链接位于https://github.com/eclipse-ee4j/jaxb-ri#maven-artifacts

    Maven coordinates for JAXB artifacts

    jakarta.xml.bind:jakarta.xml.bind-api: API classes for JAXB. Required
    to compile against JAXB.

    org.glassfish.jaxb:jaxb-runtime: Implementation of JAXB, runtime used
    for serialization and deserialization java objects to/from xml.

    JAXB fat-jar bundles:

    com.sun.xml.bind:jaxb-impl: JAXB runtime fat
    jar.

    In contrast
    to org.glassfish.jaxb artifacts, these jars have all dependency
    classes included inside. These artifacts does not contain JPMS module
    descriptors.
    In Maven projects org.glassfish.jaxb artifacts are
    supposed to be used instead.

    org.glassfish.jaxb:jaxb-runtime:jar:2.3.2拉入:

    1
    2
    3
    4
    5
    6
    7
    [INFO] +- org.glassfish.jaxb:jaxb-runtime:jar:2.3.2:compile
    [INFO] |  +- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.2:compile
    [INFO] |  +- org.glassfish.jaxb:txw2:jar:2.3.2:compile
    [INFO] |  +- com.sun.istack:istack-commons-runtime:jar:3.0.8:compile
    [INFO] |  +- org.jvnet.staxex:stax-ex:jar:1.8.1:compile
    [INFO] |  +- com.sun.xml.fastinfoset:FastInfoset:jar:1.2.16:compile
    [INFO] |  \- jakarta.activation:jakarta.activation-api:jar:1.2.1:compile

    原始答案

    以下哪些工件应该用于我的Maven项目中的JAXB RI?在Maven中,您可以使用如下配置文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <profile>
        <id>java-9</id>
       
            <jdk>9</jdk>
        </activation>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jaxb</groupId>
                jaxb-runtime</artifactId>
                <version>2.3.0</version>
            </dependency>
            <dependency>
                <groupId>javax.activation</groupId>
                activation</artifactId>
                <version>1.1.1</version>
            </dependency>
        </dependencies>
    </profile>

    依赖树显示:

    1
    2
    3
    4
    5
    6
    7
    8
    [INFO] +- org.glassfish.jaxb:jaxb-runtime:jar:2.3.0:compile
    [INFO] |  +- org.glassfish.jaxb:jaxb-core:jar:2.3.0:compile
    [INFO] |  |  +- javax.xml.bind:jaxb-api:jar:2.3.0:compile
    [INFO] |  |  +- org.glassfish.jaxb:txw2:jar:2.3.0:compile
    [INFO] |  |  \- com.sun.istack:istack-commons-runtime:jar:3.0.5:compile
    [INFO] |  +- org.jvnet.staxex:stax-ex:jar:1.7.8:compile
    [INFO] |  \- com.sun.xml.fastinfoset:FastInfoset:jar:1.2.13:compile
    [INFO] \- javax.activation:activation:jar:1.1.1:compile

    要在Eclipse中使用它,请说Oxygen.3a Release(4.7.3a)或更高版本,Ctrl-Alt-P,或右键单击项目Maven,然后选择配置文件。


    在pom.xml中添加javax.xml.bind依赖项

    1
    2
    3
    4
    5
        <dependency>
            <groupId>javax.xml.bind</groupId>
            jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>


    我按照这个URL,以下设置真的帮助了我。我在Macbook Pro中使用Java 10和STS IDE。它就像一个魅力。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
       <dependency>
        <groupId>javax.xml.bind</groupId>
        jaxb-api</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        jaxb-runtime</artifactId>
        <version>2.3.0</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        javax.activation-api</artifactId>
        <version>1.2.0</version>
    </dependency>

    我在Java 11上使用Spring Boot 2.0.5.RELEASE遇到了同样的问题。

    单独添加javax.xml.bind:jaxb-api:2.3.0并没有解决问题。我还必须将Spring Boot更新到最新的Milestone 2.1.0.M2,所以我认为这将在下一个正式版本中修复。


    不是答案,而是一个附录:我得到了因为运行groovysh(Groovy 2.4.13),如果JAVA_HOME指向Java 9安装(确切地说java version"9.0.1")失败了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    java.lang.reflect.InvocationTargetException
            at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.base/java.lang.reflect.Method.invoke(Method.java:564)
            at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:107)
            at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:129)
    Caused by: java.lang.NoClassDefFoundError: Unable to load class groovy.xml.jaxb.JaxbGroovyMethods due to missing dependency javax/xml/bind/JAXBContext
            at org.codehaus.groovy.vmplugin.v5.Java5.configureClassNode(Java5.java:400)
            at org.codehaus.groovy.ast.ClassNode.lazyClassInit(ClassNode.java:277)
            at org.codehaus.groovy.ast.ClassNode.getMethods(ClassNode.java:397)
            ...
            ..
            .
            ..
            ...
            at org.codehaus.groovy.tools.shell.Groovysh.<init>(Groovysh.groovy:135)
            at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:232)
            at org.codehaus.groovy.tools.shell.Main.<init>(Main.groovy:66)
            at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:232)
            at org.codehaus.groovy.tools.shell.Main.main(Main.groovy:163)
    ... 6 more

    解决方案是:

    • 转到github.io上的JAXB项目("JAXB是根据双许可证授予的 - CDDL 1.1和带有类路径异常的GPL 2.0")

    • 下载jaxb-ri-2.3.0.zip

    • 解压缩放置java基础结构文件的位置(在我的情况下,/usr/local/java/jaxb-ri/)。可能存在其他解决方案(可能通过SDKMAN,我不知道)

    • 确保lib子目录中的jar位于CLASSPATH上。我通过在bash启动时启动的脚本(称为/etc/profile.d/java.sh)来执行此操作,其中我添加了(在许多其他行中)以下循环:

    打包成一个功能......

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function extend_qzminynshg {
       local BASE="/usr/local/java"
       for LIB in jaxb-api.jar  jaxb-core.jar  jaxb-impl.jar  jaxb-jxc.jar  jaxb-xjc.jar; do
          local FQLIB="$BASE/jaxb-ri/lib/$LIB"
          if [[ -f $FQLIB ]]; then
             export CLASSPATH=$FQLIB:$CLASSPATH
          fi
        done
    }

    extend_qzminynshg; unset extend_qzminynshg

    它的工作原理!


    由于JavaEE现在由https://jakarta.ee/管理,因此从2.3.2开始的新Maven坐标是:

    https://github.com/eclipse-ee4j/jaxb-ri#maven-artifacts

    第一个发布的jaxb.version是2.3.2。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <properties>
      <jaxb.version>2.3.2</jaxb.version>
    </properties>

    <dependency>
      <groupId>jakarta.xml.bind</groupId>
      jakarta.xml.bind-api</artifactId>
      <version>${jaxb.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        jaxb-runtime</artifactId>
        <version>${jaxb.version}</version>
    </dependency>

    好吧,我一直有同样的问题,但我使用的是Java 8,并且不断收到此错误,我尝试了大多数解决方案。但事实证明我的maven仍然指向java 9甚至 - 虽然我将全局Java版本设置为8,一旦我修复它一切正常。

    对于任何可能遇到此类问题的人,请查看如何修复Maven以使用默认Java


    旧答案"切换到amazoncorretto解决了问题"
    新闻回答:我使用了corretto最新版,但是类似于jdk 1.8。所以无论如何我们需要手动添加依赖项


    这解决了我在Java 12上运行Apache Camel 2.24.1的依赖项的问题:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
        <dependency>
            <groupId>javax.activation</groupId>
            activation</artifactId>
            <version>1.1.1</version>
        </dependency>

        <dependency>
            <groupId>javax.xml.bind</groupId>
            jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            jaxb-core</artifactId>
            <version>2.3.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            jaxb-impl</artifactId>
            <version>2.3.0.1</version>
        </dependency>

    我知道我迟到了,但我的错误最终需要一个不同的解决方案......超级简单

    我原先去了Tomcat 9并意识到我需要7 ...我忘了将我的类路径映射回build.xml中的7版本

    希望这将在未来解决别人的错误,他设法忽略了这个简单的问题,就像我一样!


    这对我有用,我有一个用Java 8编译的Spring启动项目,但我不知道为什么有一天我的maven开始使用Java 11进行编译,在Ubuntu中我常常修复它:

    1
    sudo update-java-alternatives  -l

    这向我展示了我的电脑上可用的JDK:

    1
    java-1.11.0-openjdk-amd64      1111       /usr/lib/jvm/java-1.11.0-openjdk-amd64

    java-1.8.0-openjdk-amd64 1081 /usr/lib/jvm/java-1.8.0-openjdk-amd64

    所以我最终运行此命令来选择所需的命令:

    1
    sudo update-java-alternatives  -s java-1.8.0-openjdk-amd64

    就是这样,有关更多信息,请参阅如何使用命令更新替代方案


    编译Java 8目标时需要使用的依赖版本。在Java 8,11和12 JRE中测试的应用程序。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
            <!-- replace dependencies that have been removed from JRE's starting with Java v11 -->
            <dependency>
                <groupId>javax.xml.bind</groupId>
                jaxb-api</artifactId>
                <version>2.2.8</version>
            </dependency>
            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                jaxb-core</artifactId>
                <version>2.2.8-b01</version>
            </dependency>
            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                jaxb-impl</artifactId>
                <version>2.2.8-b01</version>
            </dependency>
            <!-- end replace dependencies that have been removed from JRE'
    s starting with Java v11 -->


    对于Java 11和gradle中的我来说,这是有用的:

    1
    2
    3
    4
    5
    6
    7
    plugins {
          id 'java'
    }

    dependencies {
          runtimeOnly 'javax.xml.bind:jaxb-api:2.3.1'
    }

    您需要将jaxb依赖项添加到maven。 glassfish实现版本2.3.2与新的jakarta EE jaxb api版本2.3.2完全兼容。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!-- API -->
    <dependency>
        <groupId>jakarta.xml.bind</groupId>
        jakarta.xml.bind-api</artifactId>
        <version>2.3.2</version>
    </dependency>

    <!-- Runtime -->
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        jaxb-runtime</artifactId>
        <version>2.3.2</version>
    </dependency>