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

本文翻译自:How to resolve java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException in Java 9

I have some code that uses JAXB API classes which have been provided as a part of the JDK in Java 6/7/8. 我有一些使用JAXB API类的代码,这些类作为Java 6/7/8中JDK的一部分提供。 When I run the same code with Java 9, at runtime I get errors indicating that JAXB classes can not be found. 当我使用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? 自Java 6以来,JAXB类已经作为JDK的一部分提供了,那么Java 9为什么不能再找到这些类?


#1楼

参考:https://stackoom.com/question/2wphK/如何解决java-lang-NoClassDefFoundError-Java-中的javax-xml-bind-JAXBException


#2楼

The JAXB APIs are considered to be Java EE APIs, and therefore are no longer contained on the default class path 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.se aggregate module is available on the class path (or rather, module path). Java 9引入了模块的概念,默认情况下, java.se聚合模块在类路径(或更确切地说是模块路径)上可用。 As the name implies, the java.se aggregate module does not include the Java EE APIs that have been traditionally bundled with Java 6/7/8. 顾名思义,该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 class path by default. 幸运的是,JDK 6/7/8中提供的这些Java EE API仍在JDK中,但默认情况下它们不在类路径中。 The extra Java EE APIs are provided in the following modules: 以下模块提供了额外的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

But I still need this to work with Java 8!!! 但是我仍然需要这个才能与Java 8一起使用!!!
If you try specifying --add-modules with an older JDK, it will blow up becase it's an unrecognized option. 如果您尝试使用较旧的JDK指定--add-modules ,它将被炸掉,因为这是无法识别的选项。 I suggest one of two options: 我建议两种选择之一:

  1. You can set any Java 9+ only options using the JDK_JAVA_OPTIONS environment variable. 您可以使用JDK_JAVA_OPTIONS环境变量设置任何仅Java 9+的选项。 This environment variable is automatically read by the java launcher for Java 9+. Java 9+的java启动器会自动读取此环境变量。
  2. You can add the -XX:+IgnoreUnrecognizedVMOptions to make the JVM silently ignore unrecognized options, instead of blowing up. 您可以添加-XX:+IgnoreUnrecognizedVMOptions以使JVM静默忽略无法识别的选项,而不会-XX:+IgnoreUnrecognizedVMOptions But beware! 但是要当心! Any other command line args you use will no longer be validated for you by the JVM. JVM将不再为您验证您使用的任何其他命令行参数。 This option works with Oracle/OpenJDK as well as IBM JDK (as of JDK 8sr4) 该选项与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.ee option. 请注意,通过指定--add-modules java.se.ee选项,可以在运行时使上述所有Java EE模块可用。 The java.se.ee module is an aggregate module that includes java.se.ee as well as the above Java EE API modules. java.se.ee模块是一个聚合模块,其中包括java.se.ee以及上述Java EE API模块。 Note, this doesn't work on Java 11 because java.se.ee was removed in Java 11. 请注意,这在Java 11上不起作用,因为在Java 11中已删除java.se.ee


Proper long-term solution: (JDK 9 and beyond) 正确的长期解决方案:(JDK 9和更高版本)

扫描二维码关注公众号,回复: 10875709 查看本文章

The Java EE API modules listed above are all marked @Deprecated(forRemoval=true) , because they are scheduled for removal in Java 11 . 上面列出的Java EE API模块都标记为@Deprecated(forRemoval=true) ,因为它们计划Java 11中 删除 So the --add-module approach will no longer work in Java 11 out of the box. 因此,-- --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 class path or module path. 在Java 11及更高版本中,您需要做的是在类路径或模块路径上包含您自己的Java EE API副本。 For example, you can add the JAX-B APIs as a maven dependency like this: 例如,您可以像这样将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 page for 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.gradle file: 将以下依赖项添加到您的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"
}

#3楼

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 9 modules can also be found at : https://www.youtube.com/watch?v=KZfbRuvv5qc 您也可以在以下网址找到有关JDK 9模块的详细介绍: https : //www.youtube.com/watch?v=KZfbRuvv5qc


#4楼

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... 虽然看起来不是一个完美的解决方案...


#5楼

For Java Web Start Execution we can use Andy Guibert's suggestion like this: 对于Java Web Start执行,我们可以使用Andy Guibert的建议,如下所示:

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

Note the extra "=" in the --add-modules. 请注意--add-modules中的额外“ =”。 See this OpenJDK Ticket or the last note in "Understanding Runtime Access Warnings" of the Java Platform, Standard Edition Oracle JDK 9 Migration Guide . 请参阅此OpenJDK票证Java平台标准版《 Oracle JDK 9迁移指南 》的“了解运行时访问警告”中的最后一个注释。


#6楼

You can use --add-modules=java.xml.bind JVM option to add xml bind module to JVM run-time environment. 您可以使用--add-modules=java.xml.bind JVM选项将xml绑定模块添加到JVM运行时环境。

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

发布了0 篇原创文章 · 获赞 8 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/asdfgh0077/article/details/105481637