1. 程式人生 > >Java9系列第三篇-同一個Jar支援多JDK版本執行

Java9系列第三篇-同一個Jar支援多JDK版本執行

![](https://img2020.cnblogs.com/other/1815316/202010/1815316-20201016080715810-604102463.png) 我計劃在後續的一段時間內,寫一系列關於java 9的文章,雖然java 9 不像Java 8或者Java 11那樣的核心java版本,但是還是有很多的特性值得關注。期待您能關注我,我將把java 9 寫成一系列的文章,大概十篇左右。 * [java9第一篇-可以在interface中定義私有方法了](http://www.zimug.com/java/java9-%e5%8f%af%e4%bb%a5%e5%9c%a8interface%e4%b8%ad%e5%ae%9a%e4%b9%89%e7%a7%81%e6%9c%89%e6%96%b9%e6%b3%95%e4%ba%86/.html) * [java9第二篇-Java9改進try-with-resources語法](http://www.zimug.com/java/java9%e6%94%b9%e8%bf%9btry-with-resources%e8%af%ad%e6%b3%95/.html) 本文內容:在Java 9增強了JAR多版本位元組碼檔案格式的支援,同一個Jar包可以包含多個Java版本的class檔案。使用這個功能,我們可以將應用程式/庫升級到新的Java版本,而不必強迫使用者升級到相同的Java版本。 ## 一、基本使用方法 多版本的位元組碼發行jar包,需要在其MANIFEST.MF中做以下的宣告: ~~~ Multi-Release: true ~~~ 在jar包的`META-INF/versions`檔案目錄裡面可以包含多個版本的class檔案,編譯結果目錄結構如下: ~~~ jar root - A.class - B.class - META-INF - versions - 9 - A.class ~~~ 假設上文中的根目錄是使用java 8 或之前版本編譯的位元組碼檔案A.calss。`META-INF/versions/9/ `是使用java 9 編寫的java程式碼的編譯結果A.class。 * 如果jar包是在JDK 8的執行時環境下執行,將使用根目錄下面的class檔案進行程式執行。 * 如果jar包是在JDK 9的執行時環境下執行,將使用`META-INF/versions/9/ `下面的class檔案進行程式執行。 假設未來這個專案升級JDK 10,決定在A.java中使用Java 10的一些新特性,可以單獨針對A.class進行語法升級,並將編譯結果a.class放置在`META-INF/versions/10/ `下面 ~~~ jar root - A.class - B.class - META-INF - versions - 9 - A.class - 10 - A.class ~~~ 現在,上面的jar包含了可以以三種Java版本執行的位元組碼檔案,A.class相容JDK 8、9、10。 ## 二、真實的例子 ### java 8程式碼 下面的類檔案程式碼我們讓它執行在Java 8的環境下 ~~~ package com.example; public class IOUtil { public static String convertToString(InputStream inputStream) throws IOException { System.out.println("IOUtil 使用java 8 版本"); Scanner scanner = new Scanner(inputStream, "UTF-8"); String str = scanner.useDelimiter("\\A").next(); scanner.close(); return str; } } ~~~ 增加一個Main.java的應用程式入口檔案,呼叫IOUtil.convertToString方法將InputStream轉換成String。 ~~~ package com.example; public class Main { public static void main(String[] args) throws IOException { InputStream inputStream = new ByteArrayInputStream("測試字串".getBytes()); String result = IOUtil.convertToString(inputStream); System.out.println(result); } } ~~~ ### Java 9程式碼 在Java 9 釋出之後,我們決定使用Java 9 的新的語法重寫IOUtil.convertToString方法。 ~~~ package com.example; public class IOUtil { public static String convertToString(InputStream inputStream) throws IOException { System.out.println("IOUtil 使用java 9 版本"); try (inputStream) { //Java9版本的增強try-with-resources String str = new String(inputStream.readAllBytes()); return str; } } } ~~~ 如上的程式碼所示,我們使用了Java 9的兩個新特性帶有inputStream引用的try-with-resource塊和新的InputStream.readAllBytes()方法。 ### 編譯 將Java8 、Java9的IOUtil.java程式碼分別在JDK8、JDK9的版本下分別編譯成class位元組碼檔案,並將class檔案按照如下的目錄結構打成儲存,並打jar包。(先按java8版本打成jar包,然後修改MANIFEST.MF檔案,新增java 9位元組碼class檔案即可) ~~~ D:\multi-release-jar-example\my-lib-jar>tree /A /F +---com | \---example | IOUtil.class | Main.class | \---META-INF | MANIFEST.MF | \---versions \---9 \---com \---example IOUtil.class ~~~ ### 執行 Main class 在JDK 9的環境下執行這個jar包 ~~~ D:\multi-release-jar-example>java -cp my-lib.jar com.example.Main IOUtil 使用java 9 版本 測試字串 ~~~ 在JDK 8的環境下執行這個jar包 ~~~ D:\multi-release-jar-example>C:\jdk1.8.0_151\bin\java -cp my-lib.jar com.example.Main IOUtil 使用java 8 版本 測試字串 ~~~ ## 歡迎關注我的部落格,裡面有很多精品合集 * 本文轉載註明出處(必須帶連線,不能只轉文字):[字母哥部落格](http://www.zimug.com)。 **覺得對您有幫助的話,幫我點贊、分享!您的支援是我不竭的創作動力!** 。另外,筆者最近一段時間輸出瞭如下的精品內容,期待您的關注。 * [《手摸手教你學Spring Boot2.0》]( https://www.kancloud.cn/hanxt/springboot2/content ) * [《Spring Security-JWT-OAuth2一本通》](https://www.kancloud.cn/hanxt/springsecurity/content) * [《實戰前後端分離RBAC許可權管理系統》](https://www.kancloud.cn/hanxt/vue-spring/content) * [《實戰SpringCloud微服務從青銅到王者》](https://www.kancloud.cn/hanxt/springcloud/content) * [《VUE深入淺出系列》](https://www.kancloud.cn/hanxt/vuejs2/