Oracle發布Java模塊系統狀態報告
Oracle Java平臺組首席架構師Mark Reinhold發表了一份關于模塊化系統的情況的報告,強調了模塊化的目標是什么。由于和已經存在的框架存在明顯的重復,特別是OSGi,報告引起發了人們的討論。
正如報告中所解釋的,以及在JSR-376和模塊化系統項目主頁中完整的詳細說明,模塊化系統是為了解決當前Java訪問模型中的兩個疏漏:
- 可靠的配置:當前一個組件通過類路徑訪問另一個組件的類時相當容易出錯,特別是嘗試使用不在類路徑里面或者存在多個版本的類的時候。
- 強封裝:沒有辦法去限制特定組件暴露給其他組件的類,外部能訪問所有的公共類。 </ul>
完整的細節能夠在報告和InfoQ之前的文章中找到,總的來說,每一個組件通常(但不一定)作為一個jar文件,其中包含了如下結構的模塊描述文件module-info.java:
module com.foo.bar {requires com.foo.baz;
exports com.foo.bar.alpha;
exports com.foo.bar.beta;
}</pre>
文件結構中包含一行或多行exports用于指出能夠被其他組件訪問的包,零行或多行requires用于指出自身需要訪問的其他模塊。該系統提供了方法用于在編譯時評估訪問類型是否具有正確的可見性(例如聲明為公共類并被所需組件導出),并在運行時評估必需的模塊是否可用,而不需要去檢查完整的類路徑。類似于OSGi中的清單文件。
OSGi的背景
OSGi是一個基于Java的模塊化系統和服務化平臺,實現了一個完整的動態的組件模型。從1998年在JSR-8第一次提出,在隨后的審核中被延遲發布(最近一次是2014年),OSGi定義了bundle(類似模塊),采用包含如下的MANIFEST.MF文件的JAR文件的形式:
Bundle-Name: Hello WorldBundle-SymbolicName: org.wikipedia.helloworld
Bundle-Description: A Hello World bundle
Bundle-ManifestVersion: 2
Bundle-Version: 1.0.0
Bundle-Activator: org.wikipedia.Activator
Export-Package: org.wikipedia.helloworld;version="1.0.0"
Import-Package: org.osgi.framework;version="1.3.0"</pre>
(例子來源于Wikipedia)
顯而易見的,盡管格式不一樣,但是目的表現的和Java模塊系統很相似。的確,Java平臺模塊系統和OSGi之間的相似性,在2005年提出的 JSR-277,“Java模塊系統”中,初次嘗試模塊化Java時就已經被注意到了。最初瞄準的Java 7,JSR-277專注簡化分發和執行Java程序包。盡管有和JSR-376幾乎一樣的名字,但兩者最初的目標有著細微差別;雖然它的任務是修復“可靠的配置”問題,但是它并不試圖解決“強封裝”的問題。相對于JSR-376,它也嘗試增加一個版本模型到Java程序包中。這些目標和OSGi提供的功能之間的相似性是完全足夠讓作者在最初考慮把OSGi作為一個解決方案,放棄的原因考慮為OSGi的版本控制太弱了。
不久之后創建的JSR-294的目標是實現“改進Java程序語言的模塊性支持”。同時針對Java 7,JSR-294新增了模塊概念(所謂的“超級包”)來修復強封裝的問題;這個概念匹配了當前的Java平臺模塊系統項目。當Java 7的目標被放棄時,JSR-277和JSR-294從2012年開始被凍結,由JSR-376代替。
OSGi和模塊化Java的另一個關聯能在JSR-291中找到,“Java SE的動態組件支持”(本質上是OSGi服務平臺發布的第四版)。JSR-291參考了JSR-277,作為最早的Java模塊系統,來主動區分兩者之間的不同作用:JSR-277關注Java中使用的靜態模塊定義,而JSR-291關注運行時動態組件的加載和卸載。
最后,JSR-376也參考了OSGi,放棄它作為有效解決方案的主要原因是因為它的范圍遠遠大于Java框架模塊系統規范。
綜上所述,多數人難以區分新的模塊系統和OSGi是正常的。但是,模塊系統和OSGi相互補充,用以服務于不同的目標,OSGi作為一個構建于 Java之上的框架,在一個持續運行的應用中,創建了一個用以動態管理bundle的環境,而模塊系統作為Java本身的新能力能夠更緊密更簡單的控制靜態模塊。
Java平臺模塊系統和OSGi的區別
為了更好的理解這一點,InfoQ請教了Holly Cummins,《Enterprise OSGi in Action》的作者之一。不過以下內容并不會徹底說清楚Java平臺模塊系統和OSGi之間的差異,只是為讀者提供一個基本的理解關于兩者目標的區別。
一方面,Java新的模塊系統將會提供更簡單的方式在編譯時檢查包和類的可見性,但是當我們詢問OSGi的bundle是否能用相同的方式使用時,Holly表示“答案是相當的復雜”。
OSGi通過bundle的清單文件來描述依賴,有兩種基本方式來創建清單文件:“代碼優先”和“清單文件優先”。代碼優先方式(使用bnd工具,和maven bundle插件),并不會在編譯時檢查依賴列表,實際上它是在編譯時生成的。在通常方式的編譯過程中,工具會根據編譯時的依賴統計出運行時的依賴。另一種方式是清單文件優先,通過Eclipse PDE工具來使用。在這種方式中,依賴被聲明在清單文件中,Eclipse IDE會使用這份清單文件統計出你的代碼能訪問的類,并高亮缺失的依賴。PDE命令行構建和一個叫做Tycho的Maven插件,都會在編譯時檢查依賴關系。但是,請注意OSGi自己并不會檢查可見性,而是通過PDE自帶的工具;因為不是所有使用PDE的團隊都會使用其中的工具,有時候可能會在編譯時造成缺少依賴。
</blockquote>新的模塊系統的另一個重要方面是能夠限定指定包對模塊的導出,這是很有用的當一批相互關聯的模塊需要互相訪問,但卻不能訪問其他內容時。正如Mark Reinhold在報告中指出的,這能夠用以下語法來實現:
module java.base { ... exports sun.reflect to java.corba, java.logging, java.sql, java.sql.rowset, jdk.scripting.nashorn; }OSGi最初并沒有這個能力,但增加之后能夠讓它比模塊系統的目標走的更遠。Holly解釋道,“所有的bundle都能夠注冊成一個解析攔截器,用以過濾匹配,因此包只會暴露給指定的bundle。當導出聲明了確定的元數據的包給bundle時,你能夠使用相同的機制來預測,或者只是在每周二瘋狂的導出包”。
查看英文原文:Oracle Publishes Report on the State of Java’s Module System
來自:http://www.infoq.com/cn/news/2015/11/java-state-module-system本文由用戶 pfmm 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!