使用 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