模塊化解惑:JSR 294、可視性與可用性的概念澄清
原創【51CTO精選譯文】JSR 294經常被描述為模塊化系統,但這是錯誤的。事實上,JSR 294提供的是一系列語言和虛擬機的特性,這些特性對OSGi和Jigsaw這些模塊化系統有好處——就好像JSR 292提供的虛擬機特性對JRuby和Jython這些動態語言運行時有好處一樣(參考閱讀:JVM動態語言支持詳解。這是Java 7當中加入的一個重要新功能。感興趣的讀者可以瀏覽51CTO的Java 7專題)。JSR 292標準化的是鏈接協議,而非鏈接行為;JSR 294標準化的是模塊的可用性(accessibility),而非模塊的界限。
就職于IBM的OSGi CTO,BJ Hargrave曾在2009年三月撰文一篇,介紹了模塊化的兩個重要概念:可視性(visibility)和可用性(accessibility)的不同。以下為全文:
可視性指的是一個類型是否能看到另一個類型。在JLS(Java Language Specification,Java語言規范)當中,這個概念被當作可觀察性(observability)被討論。在JVMS(Java Virtual Machine Specification,Java虛擬機規范)當中,這個概念與類加載相關?;旧?,這個概念描述出來就是:T類型對于S類型而言是否是可視的。在編譯時,這個概念指編譯器在編譯S類型的時候能否為類型T定位。在運行時,這個概念指S類型的類加載器能否加載(直接的或通過委托的)T類型。一個類型也可以通過反射建立可視性。即使S類型的類加載器無法加載T類型,S類型仍然可以在反射時接觸到T類型。比如說,一個對象是S類型通過I類接口直接引用的,但它仍然可能是T類型的對象。
可用性指的是一個類型能否使用(access)另一個類型,或另一個類型的成員。這在JLS和JVMS當中都進行過探討。很多人通過public,protected和private關鍵字了解到可用性這個概念。
可視性和可用性的概念有重合,但他們是兩個不同的概念;并且在我們實現Java模塊化的時候,這兩個概念必須要分開理解。首先,要使用一個類型,這個類型必須是可視的。然后才牽扯到這個類型或這個類型相關聯的成員是否可用的問題。一個類型可以同時是可視的而不可用的。
OSGi通過嚴格限制可視性實現模塊化。這很有道理,因為OSGi建立在類加載器(ClassLoader)模型之上。所以,如果bundle A導入了bundle B導出的包(packages),那么bundle B當中的其他所有包對于bundle A的類加載器而言都是不可視的。但是,如果bundle B注冊了一個服務,而實現這個服務的類型對于bundle A的類加載器而言是不可視的,bundle A仍然能夠得到這個服務的類對象(通過service.getClass())。即使那個類當中包含服務接口之外的公共方法(public methods),bundle A仍然可以呼叫這些方法。
#t#往Java當中添加一個module可用性關鍵字的意義在于,當一個類型嘗試透過模塊之間的界限使用另一個類型時,我們可以讓虛擬機強制對可用性進行控制。比如說,在上述例子當中,如果bundle A和B分屬不同的模塊(按照JSR 294的定義),那么bundle A將不能使用bundle B的服務實施類的模塊可用性成員。這樣一來,bundle的編寫者就擁有了更多控制和封裝的能力。
困難在于模塊之間界限的定義。這有關虛擬機是否強制控制可用性,而JSR 294工作組當中對這一塊仍然在不停地討論。相關問題還有是否讓Java編譯器自身理解模塊界限來進行可視性的處理,以及新的模塊可用性關鍵字。javac目前有一個簡化的可視性視圖:-classpath/-sourcepath。這和OSGi這樣的模塊化系統當中的嚴格的可視性完全不是一個等級的。讓Java編譯器擁有可視性,從而更好的滿足運行時的需求,這是個主要的挑戰。
【51CTO.com譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com。】
原文:The Programming Delusion: I am Visible but am I Accessible? 作者:BJ Hargrave