使用 jar 工具创建多版本 Jar
jar
命令可用于创建一个多版本 Jar,其中包含为 Java 8 和 Java 9 编译的同一类的两个版本,尽管有警告告诉这些类是相同的:
C:\Users\manouti>jar --create --file MR.jar -C sampleproject-base demo --release 9 -C sampleproject-9 demo
Warning: entry META-INF/versions/9/demo/SampleClass.class contains a class that
is identical to an entry already in the jar
--release 9
选项告诉 jar
在 MRJAR 的版本化条目内,即在 root/META-INF/versions/9
下包含后面的所有内容(sampleproject-9
目录中的 demo
包)。结果如下:
jar root
- demo
- SampleClass.class
- META-INF
- versions
- 9
- demo
- SampleClass.class
现在让我们创建一个名为 Main 的类,它打印 SampleClass
的 URL,并为 Java 9 版本添加它:
package demo;
import java.net.URL;
public class Main {
public static void main(String[] args) throws Exception {
URL url = Main.class.getClassLoader().getResource("demo/SampleClass.class");
System.out.println(url);
}
}
如果我们编译这个类并重新运行 jar 命令,我们会收到一个错误:
C:\Users\manouti>jar --create --file MR.jar -C sampleproject-base demo --release 9 -C sampleproject-9 demoentry: META-INF/versions/9/demo/Main.class, contains a new public class not found in base entries
Warning: entry META-INF/versions/9/demo/Main.java, multiple resources with same name
Warning: entry META-INF/versions/9/demo/SampleClass.class contains a class that
is identical to an entry already in the jar
invalid multi-release jar file MR.jar deleted
原因是 jar
工具阻止将公共类添加到版本化条目(如果它们也未添加到基本条目中)。这样做是为了使 MRJAR 为不同的 Java 版本公开相同的公共 API。请注意,在运行时,不需要此规则。它可能只适用于像 jar
这样的工具。在这种特殊情况下,Main
的目的是运行示例代码,因此我们只需在基本条目中添加一个副本。如果该类是我们只需要 Java 9 的新实现的一部分,那么它可以是非公开的。
要将 Main
添加到根条目,我们首先需要编译它以定位 Java 9 之前的版本。这可以使用 javac
的新 --release
选项来完成:
C:\Users\manouti\sampleproject-base\demo>javac --release 8 Main.java
C:\Users\manouti\sampleproject-base\demo>cd ../..
C:\Users\manouti>jar --create --file MR.jar -C sampleproject-base demo --release 9 -C sampleproject-9 demo
运行 Main 类显示 SampleClass 从版本化目录加载:
C:\Users\manouti>java --class-path MR.jar demo.Main
jar:file:/C:/Users/manouti/MR.jar!/META-INF/versions/9/demo/SampleClass.class