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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43574426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:01:28  来源:igfitidea点击:

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

javajaxbjava-9java-11java-10

提问by Andy Guibert

I have some code that uses JAXB API classes which have been provided as a part of the JDK in Java 6/7/8. When I run the same code with Java 9, at runtime I get errors indicating that JAXB classes can not be found.

我有一些使用 JAXB API 类的代码,这些类在 Java 6/7/8 中作为 JDK 的一部分提供。当我使用 Java 9 运行相同的代码时,在运行时出现错误,表明找不到 JAXB 类。

The JAXB classes have been provided as a part of the JDK since Java 6, so why can Java 9 no longer find these classes?

JAXB 类从 Java 6 开始作为 JDK 的一部分提供,那么为什么 Java 9 不再能找到这些类呢?

采纳答案by Andy Guibert

The JAXB APIs are considered to be Java EE APIs and therefore are no longer contained on the default classpath in Java SE 9. In Java 11, they are completely removed from the JDK.

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

Java 9 introduces the concepts of modules, and by default, the java.seaggregate module is available on the classpath (or rather, module-path). As the name implies, the java.seaggregate module does notinclude the Java EE APIs that have been traditionally bundled with Java 6/7/8.

Java 9 引入了模块的概念,默认情况下,java.se聚合模块在类路径(或者更确切地说,模块路径)上可用。正如其名称所暗示的,java.se汇聚模块并没有包括那些与Java 6/7/8传统上捆绑了Java EE的API。

Fortunately, these Java EE APIs that were provided in JDK 6/7/8 are still in the JDK, but they just aren't on the classpath by default. The extra Java EE APIs are provided in the following modules:

幸运的是,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

Quick and dirty solution: (JDK 9/10 only)

快速而肮脏的解决方案:(仅限 JDK 9/10)

To make the JAXB APIs available at runtime, specify the following command-line option:

要使 JAXB API 在运行时可用,请指定以下命令行选项:

--add-modules java.xml.bind

--add-modules java.xml.bind

But I still need this to work with Java 8!!!

但是我仍然需要它来与 Java 8 一起工作!!!

If you try specifying --add-moduleswith an older JDK, it will blow up because it's an unrecognized option. I suggest one of two options:

如果您尝试--add-modules使用较旧的 JDK 进行指定,它将失败,因为它是一个无法识别的选项。我建议以下两种选择之一:

  1. You can set any Java 9+ only options using the JDK_JAVA_OPTIONSenvironment variable. This environment variable is automatically readby the javalauncher for Java 9+.
  2. You can add the -XX:+IgnoreUnrecognizedVMOptionsto make the JVM silently ignore unrecognized options, instead of blowing up. But beware! Any other command-line arguments you use will no longer be validated for you by the JVM. This option works with Oracle/OpenJDK as well as IBM JDK (as of JDK 8sr4).
  1. 您可以使用JDK_JAVA_OPTIONS环境变量设置任何仅限 Java 9+ 的选项。此环境变量由Java 9+的启动器自动读取java
  2. 您可以添加-XX:+IgnoreUnrecognizedVMOptions以使 JVM 静默忽略无法识别的选项,而不是炸毁。但要小心!JVM 将不再为您验证您使用的任何其他命令行参数。此选项适用于 Oracle/OpenJDK 以及 IBM JDK(从 JDK 8sr4 开始)。


Alternate quick solution: (JDK 9/10 only)

替代快速解决方案:(仅限 JDK 9/10)

Note that you can make all of the above Java EE modules available at run time by specifying the --add-modules java.se.eeoption. The java.se.eemodule is an aggregate module that includes java.se.eeas well as the above Java EE API modules. Note, this doesn't work on Java 11because java.se.eewas removed in Java 11.

请注意,您可以通过指定--add-modules java.se.ee选项使上述所有 Java EE 模块在运行时可用。该java.se.ee模块是一个聚合模块,包括java.se.ee上述 Java EE API 模块。请注意,这不适用于 Java 11,因为java.se.ee已在 Java 11 中删除。



Proper long-term solution: (JDK 9 and beyond)

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

The Java EE API modules listed above are all marked @Deprecated(forRemoval=true)because they are scheduled for removalin Java 11. So the --add-moduleapproach will no longer work in Java 11 out-of-the-box.

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

What you will need to do in Java 11 and forward is include your own copy of the Java EE APIs on the classpath or module path. For example, you can add the JAX-B APIs as a Maven dependency like this:

在 Java 11 及以后版本中,您需要做的是在类路径或模块路径中包含您自己的 Java EE API 副本。例如,您可以将 JAX-B API 添加为 Maven 依赖项,如下所示:

<!-- API, java.xml.bind module -->
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>2.3.2</version>
</dependency>

<!-- Runtime, com.sun.xml.bind module -->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.2</version>
</dependency>

See the JAXB Reference Implementation pagefor more details on JAXB.

有关JAXB的更多详细信息,请参阅JAXB 参考实现页面

For full details on Java modularity, see JEP 261: Module System

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

For Gradle or Android Studio developer: (JDK 9 and beyond)

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

Add the following dependencies to your build.gradlefile:

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

dependencies {
    // JAX-B dependencies for JDK 9+
    implementation "jakarta.xml.bind:jakarta.xml.bind-api:2.3.2"
    implementation "org.glassfish.jaxb:jaxb-runtime:2.3.2"
}

回答by Pallavi Sonal

At the time of compilation as well as run time, add the switch --add-modules java.xml.bind

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

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

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

A good introduction of the JDK 9modules can also be found at : https://www.youtube.com/watch?v=KZfbRuvv5qc

JDK 9还可以在以下位置找到模块的良好介绍:https: //www.youtube.com/watch?v=KZfbRuvv5qc

回答by Mikhail Kholodkov

This worked for me:

这对我有用:

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


Update

更新

As @Jasper suggested, in order to avoid depending on the entire EclipseLink library, you can also just depend on EclipseLink MOXy:

正如@Jasper 所建议的,为了避免依赖整个 EclipseLink 库,您也可以只依赖 EclipseLink MOXy:

Maven

马文

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

Gradle

摇篮

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


As dependencies for my Java 8 app, which produces a *.jar which can be run by both JRE 8 or JRE 9 with no additional arguments.

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

In addition, this needs to be executed somewhere before JAXB API will be used:

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

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

Works great so far, as a workaround. Doesn't look like a perfect solution though...

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

回答by mvw

For Java Web Start Execution we can use Andy Guibert's suggestion like this:

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

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

Note the extra "=" in the --add-modules. See this OpenJDK Ticketor the last note in "Understanding Runtime Access Warnings" of the Java Platform, Standard Edition Oracle JDK 9 Migration Guide.

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

回答by Jayesh Jayanthivasan

You can use --add-modules=java.xml.bindJVM option to add xml bind module to JVM run-time environment.

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

Eg: java --add-modules=java.xml.bind XmlTestClass

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

回答by jdev

In my case (spring boot fat jar) I just add the following to pom.xml.

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

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

回答by Mr Jedi

This worked for me. Adding only jaxb-api wasn't enough.

这对我有用。仅添加 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>

回答by David Tonhofer

Not an answer, but an addendum: I got because running groovysh(Groovy 2.4.13) if JAVA_HOME points to a Java 9 installation (java version "9.0.1"to be precise) fails abysmally:

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

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

The solution was to:

解决方案是:

  • Go to the JAXB Projectat github.io ("JAXB is licensed under a dual license - CDDL 1.1 and GPL 2.0 with Class-path Exception")

  • Download jaxb-ri-2.3.0.zip

  • Unzip wherever you put your java infrastructure files (in my case, /usr/local/java/jaxb-ri/). Other solution may exist (maybe via SDKMAN, I dunno)

  • Make sure the jars in the lib subdirectory are on the CLASSPATH. I do it via a script started on bash startup, called /etc/profile.d/java.sh, where I added (among many other lines) the following loop:

  • 转到github.io上的JAXB 项目“JAXB 在双重许可下获得许可 - CDDL 1.1 和 GPL 2.0 with Class-path Exception”

  • 下载 jaxb-ri-2.3.0.zip

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

  • 确保 lib 子目录中的 jars 在CLASSPATH. 我通过一个在 bash 启动时启动的脚本来完成,名为/etc/profile.d/java.sh,我在其中添加了(在许多其他行中)以下循环:

Packed into a function...

打包成一个函数...

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

And it works!

它有效!

回答by Andremoniy

None of these solutions worked fine for me in the recent JDK 9.0.1.

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

I found that this list of dependencies is enough for a proper functioning, so you don't needto explicitly specify --add-module(though it is specified within these dependencies's pom's). The only you need is to specify this list of dependencies:

我发现此依赖项列表足以正常运行,因此您无需显式指定--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>