1. 程式人生 > >深入理解JVM(③)Java的模組化

深入理解JVM(③)Java的模組化

## 前言 JDK9引入的Java模組化系統(Java Platform Module System ,JPMS)是 對Java技術的一次重要升級,除了像之前JAR包那樣充當程式碼的容器之外,還包括: * 依賴其他模組的列表。 * 匯出的包列表,即其他模組可以使用的列表。 * 開放的包列表,即其他模組可反射訪問模組的列表。 * 使用的服務列表。 * 提供服務的實現列表。 ### 模組化系統 可配置的封裝隔離機制解決了原來類路徑上跨檔案的public類的可訪問性的問題。public型別不再意味著所有地方程式碼都可以訪問它們,**未匯出**和**未開放**的類是不能夠被外部使用。 #### 舉例說明: 新建立一個maven工程,並建立兩個module。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200630000037675.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,size_60,color_c8cae6,t_70) 在每個module的Language level 和 SDK 設定成JDK9 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200629235046232.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,size_16,color_c8cae6,t_70)![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200629235114583.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,size_16,color_c8cae6,t_70) 然後在每個module的頂層目錄中建立module-info.java ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200629235323740.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,size_60,color_c8cae6,t_70) 在ExampleOne中建立兩個不同package下的類,`ExampleFirst`和`ExampleOne`。 ```java package com.jimoer.jdkmoduleOne.test; public class ExampleFirst { private int id; private String name; private String sex; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "ExampleFirst{" + "id=" + id + ", name='" + name + '\'' + ", sex='" + sex + '\'' + '}'; } } ``` ```java package com.jimoer.jdkmoduleOne; public class ExampleOne { private int id; private String name; private String arg; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getArg() { return arg; } public void setArg(String arg) { this.arg = arg; } @Override public String toString() { return "ExampleOne{" + "id=" + id + ", name='" + name + '\'' + ", arg='" + arg + '\'' + '}'; } } ``` 然後在ExampleOne的module-info.java中宣告匯出包的路徑。 ```java module exampleOne { // 匯出包路徑 exports com.jimoer.jdkmoduleOne.test; } ``` 在ExampleTwo中宣告requires為引入包 ```java module exampleTwo { requires exampleOne; } ``` 然後在ExampleTwo中使用ExampleOne中的類 ```java ublic class ExampleTwo { public static void main(String[] args) { ExampleFirst first = new ExampleFirst(); first.setId(1); first.setName("餘歡水"); first.setSex("男"); System.out.println(first); } } ``` 執行結果: ```java ExampleFirst{id=1, name='餘歡水', sex='男'} ``` 但是當在ExampleTwo中引用ExampleOne中非匯出包下的類時就會編譯出錯。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020063022185537.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,size_60,color_c8cae6,t_70) 如上圖提示,所有不被匯出的包預設都被封裝在模組裡面。 #### 模組的相容性 為了使可配置的封裝隔離機制能夠相容傳統的類路徑查詢機制,JDK9提出了與“類路徑”(ClassPath)相對應的“**模組路徑**”(ModulePath)的概念。只要放在類路徑上的JAR檔案,都會被當作傳統的JAR包來對待;相應地,只要放在模組路徑上的JAR檔案,即使沒有使用JMOD字尾,甚至不包含module-info.class檔案,也仍然會被當作一個模組來對待。 為了保證Java應用升級到JDK9之後依然使用傳統的類路徑,不會受到影響,制定了三條規則來保證相容性。 * __JAR檔案在類路徑的訪問規則__:所有類路徑下的JAR檔案及其他資原始檔,都被視為自動打包在一個匿名模組(Unnamed Module)裡,這個匿名模組幾乎是沒有任何隔離的,它可以看到和使用類路徑上所有的包、JDK模組中所有的匯出包,以及模組路徑是哪個所有模組中匯出的包。 * __模組在模組路徑的訪問規則__:模組路徑下的具名模組(Named Module)只能訪問到她依賴定義中列明依賴的模組和包,匿名模組裡所有的內容對具名模組來說都是不可見的,即具名模組看不見傳統JAR包的內容。 * __JAR檔案在模組路徑的訪問規則__:如果把一個傳統的、不包含模組定義的JAR檔案放置到模組路徑中,它就會變成一個自動模組(Automatic Module)。 ### 模組化下的類載入器 JDK9為了保證相容性,依然保持了三層類載入器架構以及雙親委派模型。但是為了模組化系統的順利實施,還是對類載入器做了一些改動。 * 首先,擴充套件類載入器(Extension Class Loader)被平臺類載入器(Platform Class Loader)取代。因為模組化天然的支援擴充套件,自然不需要在存在擴充套件類載入器了。 * 其次,平臺類載入器和應用類載入器都不再派生自java.net.URLClassLoader,如果有程式直接依賴了這種繼承關係,或者依賴了URLClassLoader類特定方法,那程式碼很可能會在JDK9及更高版本的JDK中崩潰。 * 最後,==JDK9中雖然仍然維持著三層類載入器和雙親委派架構,但類載入的委派關係也發生了變動。當平臺及應用程式類載入器收到類載入請求,在委派給父載入器載入前,要先判斷該類是否能夠歸屬到某一個系統模組中,如果可以找到這樣的歸屬關係,就要優先委派給負責哪個模組的載入器完成載入,這可以算是對雙親委派的第四次破壞==。 JDK9前後三層類載入器的架構圖對比如下: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200630231507191.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,size_60,color_c8ca