Java 9 版本中增强了Jar 包多版本字节码文件格式支持,也就是说在同一个 Jar 包中我们可以包含多个 Java 版本的 class 文件,这样就能做到 Jar 包升级到新的 Java 版本时不用强迫使用方为了使用新 Jar 包而升级自己的业务模块 Java 版本,也不用针对不同最低支持 Java 版本提供不同的 Jar,真正的做到了一个 Jar 包兼容所有的目的。
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 jdk9
这样就实现了同一个 Jar 包中包含多个 Java 版本的 class 文件,用不同版本 JDK 执行的时候,运行不同版本的 class 文件。
也可以使用 Intellij IDEA 来创建多版本 Jar,这里是参考文档: Creating Multi-Release JAR Files in IntelliJ IDEA
Maven 项目配合多版本 Jar 示例
多数情况下,我们不会手动创建项目目录并编译,一般用 Maven 来管理项目。本示例演示如何在 Maven 下进行多版本 Jar 包的管理。
创建一个 Maven 项目,结构如下
和上例类似, 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 DefaultVersion().version())); }}
旧版本代码,放在 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 Runtime.version().toString(); }}