Java SE 9 多版本兼容 JAR 包示例

Posted 敲代码的老贾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java SE 9 多版本兼容 JAR 包示例相关的知识,希望对你有一定的参考价值。

说明

Java 9 版本中增强了Jar 包多版本字节码文件格式支持,也就是说在同一个 Jar 包中我们可以包含多个 Java 版本的 class 文件,这样就能做到 Jar 包升级到新的 Java 版本时不用强迫使用方为了使用新 Jar 包而升级自己的业务模块 Java 版本,也不用针对不同最低支持 Java 版本提供不同的 Jar,真正的做到了一个 Jar 包兼容所有的目的。

本文通过以下示例来说明多版本 Jar 包的使用。

环境准备

机器上应该有多个版本的 JDK 用于测试,并且至少有一个是 JDK 9 或者更高版本。

命令行编译示例

注:本示例无需使用 IDE ,我们用最原始的方式创建一个多版本的 Jar 包。

新建一个文件夹,用项目名称命名,并且在其中把 ​​src​​ 目录,包名都建好,可以自定义,后续编译命令自行调整即可。

Java

​src\\main\\java\\git\\snippet​​ 目录下存的是旧版本 JDK 编写的代码。在这个目录下新建两个类。

package git.snippet;

/**
* Java SE 9 Multi-Release JAR Files示例
*
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/8/14
* @since
public class App
public static void main(String[] args)
Helper.hello(args[0]);

package git.snippet;

/**
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/8/14
* @since
public class Helper
public static void hello(String name)
// jdk 9+不能用_作为变量
String _ = "hello";
System.out.println(_ + ", "

​src\\main\\java9\\git\\snippet​​ 目录下存的是新版本 JDK 编写的代码。我们需要把 ​​Helper​​ 类用新的 JDK 版本特性来实现。代码如下

package git.snippet;

/**
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/8/14
* @since
public class Helper
public static void hello(String name)
// 旧版本用_作为变量,jdk9不能用_作为变量
String fixName = "hello";
System.out.println(fixName + ", " + name + " from jdk9");

创建好上述类以后,项目结构如下

Java

接下来是编译,在项目目录下,用 JDK 9+的 ​​javac​​ 执行如下两个编译命令

C:\\jdk\\jdk-11\\bin\\javac --release 7 -d classes src\\main\\java\\git\\snippet\\*.java

提示信息如下(仅显示了警告)

D:\\git\\hello-mrjar>C:\\jdk\\jdk-11\\bin\\javac --release 7 -d classes src\\main\\java\\git\\snippet\\*.java
src\\main\\java\\git\\snippet\\Helper.java:11: 警告: 从发行版 9 开始, _ 为关键字, 不能用作标识符
String _ = "hello";
^
src\\main\\java\\git\\snippet\\Helper.java:12: 警告: 从发行版 9 开始, _ 为关键字, 不能用作标识符
System.out.println(_ + ", " + name);
^
2
C:\\jdk\\jdk-11\\bin\\javac --release 9 -d classes-9 src\\main\\java9\\git\\snippet\\*.java

无提示信息和报错信息。

接下来是通过 JDK 9+ 的 ​​jar​​ 进行打包,打包的时候,运行如下打包命令

C:\\jdk\\jdk-11\\bin\\jar --create --file target/hello-mrjar.jar --main-class git.snippet.App -C classes . --release 9 -C classes-9 .

如果提示如下报错信息

java.nio.file.NoSuchFileException: C:\\Users\\zhuiz\\AppData\\Local\\Temp\\hello-mrjar.jar9462053262887373909.jar -> target\\hello-mrjar.jar
at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:85)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
at java.base/sun.nio.fs.WindowsFileCopy.move(WindowsFileCopy.java:395)
at java.base/sun.nio.fs.WindowsFileSystemProvider.move(WindowsFileSystemProvider.java:292)
at java.base/java.nio.file.Files.move(Files.java:1422)
at jdk.jartool/sun.tools.jar.Main.validateAndClose(Main.java:466)
at jdk.jartool/sun.tools.jar.Main.run(Main.java:349)
at jdk.jartool/sun.tools.jar.Main.main(Main.java:1681)

则手动在项目目录下建立一个target文件夹,再次执行打包命令,错误解决。

在 ​​target​​ 目录下,包已经打好 ​​hello-mrjar.jar​​ 。

最后进行测试,用JDK 9之前的 ​​java​​ 来执行这个 ​​jar​​ 包。

C:\\jdk\\jdk1.8\\bin\\java -jar hello-mrjar.jar Grey

输出如下

hello, Grey

用 JDK 9+ 的 ​​java​​ 来执行这个 ​​jar​​ 包。

C:\\jdk\\jdk-11\\bin\\java -jar hello-mrjar.jar Grey

输出如下

hello, Grey from

这样就实现了同一个 Jar 包中包含多个 Java 版本的 class 文件,用不同版本 JDK 执行的时候,运行不同版本的 class 文件。

也可以使用 ​​Intellij IDEA​​ 来创建多版本 Jar,这里是参考文档: ​​Creating Multi-Release JAR Files in IntelliJ IDEA​

Maven 项目配合多版本 Jar 示例

多数情况下,我们不会手动创建项目目录并编译,一般用 Maven 来管理项目。本示例演示如何在 Maven 下进行多版本 Jar 包的管理。

创建一个 Maven 项目,结构如下

Java

和上例类似, ​​src\\main\\java9​​ 文件夹中是对应的新版本 JDK 的代码

​src\\main\\java​​ 文件夹中是对应的旧版本的 JDK 代码。

代码清单如下

package git.snippet;

public class App
public static void main(String[] args)
System.out.println(String.format("Running on %s", new

旧版本代码,放在 ​​src\\main\\java​​ 对应的包下。

package git.snippet;

public class DefaultVersion

public String version()
System.out.println("use jdk");
return System.getProperty("java.version");

新版本代码,放在 ​​src\\main\\java9​​ 对应的包下。

package git.snippet;

public class DefaultVersion

public String version()
System.out.println("use jdk 9+");
return

​pom.xml​​ 文件配置,注意,相关的文件夹或者包有调整,需要做对应的调整。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>git.snippet</groupId>
<artifactId>hello-mrjar-with-maven</artifactId>
<version>1.0</version>

<properties>
<java.version>11</java.version>
<maven.compiler.source>$java.version</maven.compiler.source>
<maven.compiler.target>$java.version</maven.compiler.target>
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>compile-java-8</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compileSourceRoots>
<!---旧版本代码的位置-->
<compileSourceRoot>$project.basedir/src/main/java</compileSourceRoot>
</compileSourceRoots>
</configuration>
</execution>
<execution>
<id>compile-java-9</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>9</release>
<compileSourceRoots>
<!---新版本代码的位置-->
<compileSourceRoot>$project.basedir/src/main/java9</compileSourceRoot>
</compileSourceRoots>
<outputDirectory>$project.build.outputDirectory/META-INF/versions/9</outputDirectory>
</configuration>
</execution>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>$maven-jar-plugin.version</version>
<configuration>
<archive>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
<manifest>
<!--设置主方法入口-->
<mainClass>git.snippet.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

然后用新版本的 JDK 进行打包,在项目目录下执行

mvn clean package -Dmaven.test.skip=true

提示

[INFO] --- maven-jar-plugin:3.2.0:jar (default-jar) @ hello-mrjar-with-maven ---
[INFO] Building jar: D:\\git\\hello-mrjar-with-maven\\target\\hello-mrjar-with-maven-1.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.447 s
[INFO] Finished at: 2022-08-15T11:29:48+08:00

说明打包成功。然后进入 ​​target​​ 目录,进行验证

用旧版本的 Java 执行 Jar 包

C:\\jdk\\jdk1.8\\bin\\java -jar hello-mrjar-with-maven-1.0.jar

输出

use jdk
Running on 1.8.0_202

用新版本的 Java 执行 Jar 包

C:\\jdk\\jdk-11\\bin\\java -jar hello-mrjar-with-maven-1.0.jar

输出

use jdk 9+
Running on 11.0.15+8-LTS-149


以上是关于Java SE 9 多版本兼容 JAR 包示例的主要内容,如果未能解决你的问题,请参考以下文章

我一套java代码里既要连接mysql5数据库,又要连mysql8版本,驱动jar包不兼容怎么办?

windows下jar无法在linux下运行

升级SpringBoot 2.1.X 各jar包冲突、兼容问题

关于Java 的 poi jar包

JAVA_SE基础——58.如何用jar命令对java工程进行打包

完美解决mysql 8.0高版本兼容性各种问题