首頁 > 軟體

Java SE 9 多版本相容 JAR 包範例

2022-08-16 14:01:56

說明

Java 9 版本中增強了Jar 包多版本位元組碼檔案格式支援,也就是說在同一個 Jar 包中我們可以包含多個 Java 版本的 class 檔案,這樣就能做到 Jar 包升級到新的 Java 版本時不用強迫使用方為了使用新 Jar 包而升級自己的業務模組 Java 版本,也不用針對不同最低支援 Java 版本提供不同的 Jar,真正的做到了一個 Jar 包相容所有的目的。

本文通過以下範例來說明多版本 Jar 包的使用。

環境準備

機器上應該有多個版本的 JDK 用於測試,並且至少有一個是 JDK 9 或者更高版本。

命令列編譯範例

注:本範例無需使用 IDE ,我們用最原始的方式建立一個多版本的 Jar 包。

新建一個資料夾,用專案名稱命名,並且在其中把 src 目錄,包名都建好,可以自定義,後續編譯命令自行調整即可。

srcmainjavagitsnippet 目錄下存的是舊版本 JDK 編寫的程式碼。在這個目錄下新建兩個類。

package git.snippet;

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

/**
 * @author <a href="mailto:410486047@qq.com" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >Grey</a>
 * @date 2022/8/14
 * @since 1.7
 */
public class Helper {
    public static void hello(String name) {
        // jdk 9+不能用_作為變數
        String _ = "hello";
        System.out.println(_ + ", " + name);
    }
}

srcmainjava9gitsnippet 目錄下存的是新版本 JDK 編寫的程式碼。我們需要把 Helper 類用新的 JDK 版本特性來實現。程式碼如下

package git.snippet;

/**
 * @author <a href="mailto:410486047@qq.com" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >Grey</a>
 * @date 2022/8/14
 * @since 9
 */
public class Helper {
    public static void hello(String name) {
        // 舊版本用_作為變數,jdk9不能用_作為變數
        String fixName = "hello";
        System.out.println(fixName + ", " + name + " from jdk9");
    }
}

建立好上述類以後,專案結構如下:

接下來是編譯,在專案目錄下,用 JDK 9+的 javac 執行如下兩個編譯命令

C:jdkjdk-11binjavac --release 7 -d classes srcmainjavagitsnippet*.java

提示資訊如下(僅顯示了警告)

D:githello-mrjar>C:jdkjdk-11binjavac --release 7 -d classes srcmainjavagitsnippet*.java
srcmainjavagitsnippetHelper.java:11: 警告: 從發行版 9 開始, '_' 為關鍵字, 不能用作識別符號
        String _ = "hello";
               ^
srcmainjavagitsnippetHelper.java:12: 警告: 從發行版 9 開始, '_' 為關鍵字, 不能用作識別符號
        System.out.println(_ + ", " + name);
                           ^
2 個警告
C:jdkjdk-11binjavac --release 9 -d classes-9 srcmainjava9gitsnippet*.java

無提示資訊和報錯資訊。

接下來是通過 JDK 9+ 的 jar 進行打包,打包的時候,執行如下打包命令

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

如果提示如下報錯資訊:

java.nio.file.NoSuchFileException: C:UserszhuizAppDataLocalTemphello-mrjar.jar9462053262887373909.jar -> targethello-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:jdkjdk1.8binjava -jar hello-mrjar.jar Grey

輸出如下

hello, Grey

用 JDK 9+ 的 java 來執行這個 jar 包。

C:jdkjdk-11binjava -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 專案,結構如下:

和上例類似, srcmainjava9 資料夾中是對應的新版本 JDK 的程式碼

srcmainjava 資料夾中是對應的舊版本的 JDK 程式碼。

程式碼清單如下:

package git.snippet;
public class App {
    public static void main(String[] args) {
        System.out.println(String.format("Running on %s", new DefaultVersion().version()));
    }
}

舊版本程式碼,放在 srcmainjava 對應的包下。

package git.snippet;
public class DefaultVersion {
    public String version() {
        System.out.println("use jdk");
        return System.getProperty("java.version");
    }
}

新版本程式碼,放在 srcmainjava9 對應的包下。

package git.snippet;

public class DefaultVersion {

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

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:githello-mrjar-with-maventargethello-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
[INFO] ------------------------------------------------------------------------

說明打包成功。然後進入 target 目錄,進行驗證

用舊版本的 Java 執行 Jar 包

C:jdkjdk1.8binjava -jar hello-mrjar-with-maven-1.0.jar
複製程式碼

輸出:

use jdk
Running on 1.8.0_202

用新版本的 Java 執行 Jar 包

C:jdkjdk-11binjava -jar hello-mrjar-with-maven-1.0.jar

輸出:

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

到此這篇關於Java SE 9 多版本相容 JAR 包範例的文章就介紹到這了,更多相關Java JAR 包內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com