如何在Java 9中解决java.lang.NoClassDefFoundError:javax / xml / bind / JAXBException

问题描述 投票:590回答:23

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

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

java jaxb java-9 java-11 java-10
23个回答
914
投票

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:

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,它会爆炸,因为它是一个无法识别的选项。我建议两种选择之一:

  1. 您可以使用JDK_JAVA_OPTIONS环境变量设置任何仅Java 9+选项。这个环境变量是用于Java 9+的automatically read启动器的java
  2. 您可以添加-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),因为它们是scheduled for removal中的Java 11。所以--add-module方法将不再适用于Java 11开箱即用。

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

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.11</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.2.11</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.11</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>

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

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

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

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"
}

10
投票

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

        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>${jaxb-api.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>${jaxb-api.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>${jaxb-api.version}</version>
        </dependency>

9
投票

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

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'

8
投票

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

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

注意--add-modules中的额外“=”。请参阅this OpenJDK TicketJava Platform, Standard Edition Oracle JDK 9 Migration Guide的“了解运行时访问警告”中的最后一个注释。


7
投票

2019年4月更新

JAXB版本的Changelong是在https://javaee.github.io/jaxb-v2/doc/user-guide/ch02.html

摘录:

    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坐标为JAXB工件

jakarta.xml.bind:jakarta.xml.bind-api:JAXB的API类。需要针对JAXB进行编译。

org.glassfish.jaxb:jaxb-runtime:JAXB的实现,用于序列化和反序列化java对象到/从xml反序列化的运行时。

JAXB fat-jar包:

com.sun.xml.bind:jaxb-impl:JAXB运行时胖jar。

与org.glassfish.jaxb工件相比,这些jar包含所有依赖类。这些工件不包含JPMS模块描述符。在Maven项目中,应该使用org.glassfish.jaxb工件代替。

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

[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中使用Which artifacts should I use for JAXB RI in my Maven project?之后,您可以使用以下配置文件:

<profile>
    <id>java-9</id>
    <activation>
        <jdk>9</jdk>
    </activation>
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>
</profile> 

依赖树显示:

[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,然后选择配置文件。


5
投票

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

   <dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.0</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>javax.activation-api</artifactId>
    <version>1.2.0</version>
</dependency>

5
投票

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

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


5
投票

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

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

3
投票

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

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 Project(“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,在这里我添加了(在许多其他行中)以下循环:

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

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

它的工作原理!


3
投票

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

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

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

<properties>
  <jaxb.version>2.3.2</jaxb.version>
</properties>

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

2
投票

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

对于任何可能遇到此类问题的人,请查看How to fix Maven to use default Java


186
投票

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

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

2
投票

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


0
投票

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

我最初部署到Tomcat 9并意识到我需要7 ...我忘了将我的类路径映射回build.xml中的7版本

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


0
投票

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

sudo update-java-alternatives  -l

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

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

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

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

就是这样,更多的是看看How to use the command update alternatives


0
投票

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

        <!-- replace dependencies that have been removed from JRE's starting with Java v11 -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2.8</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.2.8-b01</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2.8-b01</version>
        </dependency>
        <!-- end replace dependencies that have been removed from JRE's starting with Java v11 -->

58
投票

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

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

<dependencies>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>activation</artifactId>
        <version>1.1.1</version>
    </dependency>
</dependencies>

37
投票

这对我有用:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>eclipselink</artifactId>
    <version>2.7.0</version>
</dependency>

更新

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

Maven的

<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>org.eclipse.persistence.moxy</artifactId>
    <version>2.7.3</version>
</dependency>

摇篮

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

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

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

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

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


24
投票

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

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

17
投票

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

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

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

有关JDK 9模块的详细介绍也可以在以下网站找到:https://www.youtube.com/watch?v=KZfbRuvv5qc


16
投票

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

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

  • jaxb-api
  • 一个jaxb实现

作为一个实现,我选择使用glassfish的参考实现来摆脱旧的com.sun类/库。因此,我添加了我的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>

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


11
投票

为了解决这个问题,我在项目中导入了一些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

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

11
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.