Java 9模組化概觀 - iThome
文章推薦指數: 80 %
而在最新的JDK9預覽版中,也可以玩玩Java模組平臺系統(Java Platform Module System),也就是JSR376的實作了。
JAR檔案的挑戰. 撰寫Java的開發者都知道 ...
移至主內容
文/林信良
|
2017-03-12發表
從Java7開始,就一直嚷嚷著要納入的模組化架構,到了Java8不見推出,這中間又過了好幾年,最後來到了Java9,而Java9又因開發不及,從原定的2017年3月改到了2017年7月,如果沒有意外,目前看來,應該是可以如期推出。
而在最新的JDK9預覽版中,也可以玩玩Java模組平臺系統(JavaPlatformModuleSystem),也就是JSR376的實作了。
JAR檔案的挑戰
撰寫Java的開發者都知道,目前的Java使用JAR檔案來包裝一堆類別檔案,而這些類別檔案會使用套件(package)來加以組織,在編譯或運行Java應用程式時,必須指定類別路徑(CLASSPATH),一開始這不是什麼問題,只是隨著Java應用的場合越來越多,挑戰也就越來越多。
舉例而言,JAR檔案定義在類別路徑中的順序,經常會有同名類別遮蓋的問題;JAR對包裝的類別沒有封裝機制,即使開發中的程式庫想隱藏底層使用到的實作品,然而,只要是public的類型,對客戶端就是可見的;簡而言之,JAR檔案充其量只是個方便傳送的器皿罷了,它沒辦法表示彼此之間的依賴關係,想想看,有多少次發生ClassNotFoundException時,你總是想不透,到底還缺少了哪個JAR檔案呢?
JavaSE自己也身受其害。
從10MB以下的JDK1.1,到現在200多MB的JDK8,JDK越來越肥大,在錯綜複雜的依賴關係下,有些標準API就算不需要,也必須全盤接受,這對現今的IoT是個挑戰,雖然Java8之後有了compactprofile,可定義三種JavaSE的子集,然而,也只是在有限程度下緩解了這個問題。
而且,還有更多其他的問題待解決,這部份可以參考〈ProjectJigsawisReallyCominginJava9〉(https://goo.gl/15XuYl),某些工具試圖解決部份問題,像是Maven、OSGi等,然而由於一些技術、政治或商業性考量,Java9終究是採用了Jigsaw來解決(部份的)問題。
類別路徑淡出,模組路徑登場
具體來說,Java9中的模組仍是使用JAR檔案,這是為了善用現有的工具,以緩解導入或遷移的負擔,一個模組化JAR檔案(modularJARfile)與一般JAR檔案之間的差別,在於根目錄下是否包含一個module-info.class,而它又是由一個module-info.java檔案編譯而來,這個.java是作為模組描述器(Moduledescriptor)使用。
一個最簡單的模組描述器,可以只包括modulecc.openhome.app{}這樣的內容,雖然是個.java檔案,但它不是Java原始碼,開發者不用擔心module成為保留字,而影響了既有的Java原始碼,因為這一個不是Java的.java,以及編譯出來的.class,只是讓編譯器或執行環境能理解這是一個模組。
模組名稱必須是唯一的,與套件名稱類似的,建議使用網域名稱的相反模式,通常是套件名稱的前置部份,如果應用程式依賴在某些模組,在編譯的時候,必須使用--module-path(簡寫-p)或--module-source-path來指定模組路徑,執行時也要指定--module-path,或者是在想要指定起始模組時使用--module(簡寫-m)。
在Java9推出之後,未來在開發上當然是鼓勵定義模組的,而類別路徑的指定方式,基於向後相容性(Backwardcompatibility)考量仍舊支援,實際上,一個模組化JAR檔案若是指定於類別路徑中,就會被當成是一般JAR檔案,然而,類別路徑未來應走向逐漸淡出的道路,既有的程式庫在可能的情況下,也要逐漸遷移至新的模組系統。
模組描述器概觀
最簡單的module-info.java,可以只包括modulecc.openhome.app{},這樣的模組描述器沒有指定任何依賴模組,這表示它依賴在最基本的java.base模組(若使用到java.sql等其他模組,就會編譯失敗)。
JavaSE9將過往有著錯綜複雜依賴關係的標準API,畫分為java.logging、java.sql、java.xml等各個模組,而這些模組最終都依賴在一個java.base模組,它包含了java.lang、java.io等基本套件,而整個JavaSE被定義為一個java.se模組。
一個有著依賴關係的模組描述器,會像是:
modulecc.openhome.app{
requirescc.openhome.openscad;
requirespubliccc.openhome.math;
exportscc.openhome.turtle;
}這部分表示了一些事情——cc.openhome.app模組依賴在cc.openhome.openscad,以及前者的類別對後者匯出(exports)的公開類別,具有讀取性(Readability)。
而且,要注意的是,讀取性僅定義了模組的依賴關係圖,例如cc.openhome.app對cc.openhome.openscad是顯式(explicitly)依賴,然而,cc.openhome.openscad可能依賴在其他模組上,因而這些模組也被cc.openhome.app隱式(implicitly)依賴,而對於modulecc.openhome.app{},它也隱式依賴在java.base。
只有讀取性,並不代表著可使用被依賴模組中的類別,例如,若有模組requirescc.openhome.app,而上面的模組描述器中並沒有exportscc.openhome.turtle的話(cc.openhome.app中定義的套件),那麼就無法使用cc.openhome.turtle套件中的類別,這表示被public定義的類別不再是全域可見了,定義模組時可以使用exports決定其存取性(Accessibility),因而模組可以實現更強的封裝性(Strongencapsulation)。
有一個問題是,如果有模組requirescc.openhome.app,而cc.openhome.openscad模組中,傳回了cc.openhome.math套件中的類別類型,那麼,最前頭的模組可以也使用該類型嗎?
對此,簡單的想法是,讓開發者自行在一開始的模組描述器,也加上requirescc.openhome.openscad,不過,這作法麻煩也不可靠,如果cc.openhome.app願意的話,只要加上requirespubliccc.openhome.math,就可以解決這個問題。
相容性與遷移
無疑地,既有的應用程式,還是要能在Java9上運行的,其中一個作法如前所述,一個模組化JAR檔案若是指定於類別路徑中,會被當成是一般JAR檔案,實際上,置於類別路徑中的類別,都會被歸類在一個未命名模組(unnamedmodule),未命名模組對任何模組都具有讀取性,對被模組匯出的套件中的任何類別具有存取性。
而在既有程式庫的遷移上,有一個簡單的情境是,如果某個JAR檔案未依賴類別路徑上的其他程式庫,而且經檢查僅依賴在java.base模組,那麼,這個JAR檔案可以進一步定義為模組化檔案;接著,若另一個JAR檔案依賴在這個JAR,就可以定義其依賴在新定義的模組,以及其他的java.sql等模組上,依此類推、完成遷移。
整體而言,這是一種自底而上的遷移(Bottom-upmigration)方式。
當然,實際的依賴情況可能更複雜,可以使用jdeps之類的工具來檢查相依關係,而開發者也需要瞭解更多模組化的細節,此時,SimonRitter的演講〈ProjectJigsawinJDK9:ModularityComesToJava〉(https://goo.gl/3Scf6n)會是個好的開始。
在這之後,OpenJDK官方的〈TheStateoftheModuleSystem〉(https://goo.gl/HFN9Em)是個詳盡的文件。
專欄作者
林信良
因在網路上經營「良葛格學習筆記」(openhome.cc)而聞名,曾任昇陽教育訓練中心技術顧問、甲骨文教育訓練中心授權講師,目前為自由工作者,專長為技術寫作、翻譯與教育訓練。
喜好研究程式語言、框架、社群,從中學習設計、典範及文化。
閒暇之餘記錄所學,技術文件涵蓋C/C++、Java、Ruby/Rails、Python、JavaScript、Haskell等多個領域。
熱門新聞
Chrome與Edge中的拼字檢查功能可能外洩用戶密碼
2022-09-19
Uber疑似被駭,內部多項系統遭取得權限
2022-09-19
以太坊合併後,GPU挖礦已幾乎無利可圖
2022-09-19
全家史上最大規模POS改造,不只砸上億導混合雲,雙模式三大設計一機通吃大小店種和戶外擺攤
2022-09-15
【資安週報】2022年9月12日到9月16日
2022-09-18
與Nvidia關係決裂?EVGA退出顯示卡市場
2022-09-19
星巴克22萬新加坡顧客資料遭駭客公開兜售
2022-09-19
【資安日報】2022年9月19日,Uber特權管理系統管理員帳密遭竊、密碼管理解決方案業者LastPass針對8月遭駭透露更多調查結果
2022-09-19
Advertisement
2022iThome鐵人賽
專題報導
iThome2022資安大調查(下)
iThome2022資安大調查(上)
【iThome2022CIO大調查(下)】各產業數位轉型加速,IT大步邁向雲原生
分散式RAID躍居主流儲存應用
【iThome2022CIO大調查(中)】企業IT新戰力
更多專題報導
延伸文章資訊
- 1JVM 與module-path - OpenHome.cc
首先,對於模組平臺系統要知道的第一件事是,它跟Java 程式語言本身沒有關係,而是為了管理程式庫本身的功能封裝、程式庫之間的相依性等需求而存在,將一個不支援模組 ...
- 2遷移!往Java 9前進!
修改 java.base 的module-info顯然不是可行的方式,在Oracle JDK中提供了一個非標準引數 --add-exports , 可用來放寬(或說是破壞)模組封裝,例如,可以在...
- 3Java 9 模块系统 - 菜鸟教程
工件的格式可以是传统的JAR 文件或是Java 9 新增的JMOD 文件。这个文件由根目录中的源代码文件module-info.java 编译而来。该模块声明文件可以描述模块的不同特征。
- 4Java模組化 - 恆逸教育訓練中心
Java 5新增加強型迴圈、Annotation與Generic,Java 8新增的Lambda,都讓Java程式設計語言產生很大的變化。Java 9新增的模組化,雖然對程式設計語言本身並 ...
- 5Java9系列第8篇-Module模組化程式設計 - IT人
我計劃在後續的一段時間內,寫一系列關於java 9的文章,雖然java 9 不像Java 8或者Java 11那樣的核心java版本,但是還是有很多的特性值得關注。