提问:
我有一些使用JAXB API类的代码,这些类在Java 6/7/8版本中被作为JDK的一部分。当我用Java 9运行同样的代码运行时,我得到的错误提示是找不到 JAXB类。
JAXB类从Java 6开始就作为JDK的一部分提供,那么为什么Java 9不能再找到这些类呢?
回答:
JAXB API被认为是Java EE API,因此在Java SE 9中不再包含在默认的classpath上。 在Java 11中,它们被完全从JDK中移除。
Java 9引入了模块的概念,默认情况下,java.se聚合模块在classpath(或者说,模块路径)上可用。顾名思义,java.se聚合模块不包括传统上与Java 6/7/8捆绑的Java EE APIs。
幸运的是,JDK 6/7/8中提供的这些Java EE API仍在JDK中,只是默认情况下不在classpath上。额外的Java EE APIs是在以下模块中提供的。
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 APIs在运行时可用,请指定以下命令行选项。
–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模块。注意,这在Java 11上不起作用,因为java.se.ee在Java 11中被移除。
正确的长期解决方案。(JDK 9及以后)
上面列出的Java EE API模块都被标记为@Deprecated(forRemoval=true),因为它们被计划在Java 11中删除。因此,–添加模块的方法在Java 11开箱即用的情况下将不再适用。
在Java 11中,你需要做的是在classpath或模块路径上包括你自己的Java EE APIs的副本。例如,您可以将JAX-B APIs作为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>
复制代码
关于JAXB的更多细节,请参见JAXB参考实现页面。
关于Java模块化的全部细节,请参见JEP 261。模块系统
适用于Gradle或Android Studio开发人员。(JDK 9及以上版本)
在你的 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"
}
复制代码