讀古今文學網 > Java程序員修煉之道 > 14.2 多語言編程 >

14.2 多語言編程

從第5章開始,你已經無數次見證了JVM作為語言運行時平台的奇妙。第1章介紹的OpenJDK項目在Java 7的發佈週期中成了Java的參考實現。非常有趣的是JVM已經發展成了一個語言無關的、真正支持多語言編程的虛擬機。

特別是隨著Java 7的發佈,Java語言喪失了在VM上的特權。平台上的所有語言現在都一視同仁。因此人們對添加之於備選語言非常重要、而對Java本身只有邊際效益的VM特性表現出了強烈的興趣。

這一工作是在達芬奇機(Da Vinci Machine)子項目中開展的,這一項目也叫做mlvm(多語言VM)。在這一項目中培育出的特性會被引入源碼主幹中。5.5節中的invokedynamic就是這樣的例子,但還有很多對非Java語言非常實用的其他特性。也有需要解決的問題。

我們先來看看這些語言特性中的第一個:不同的語言運行在同一個JVM中彼此進行無障礙交流的辦法。

14.2.1 語言的互操作性及元對像協議

語言平等是向了不起的多語言編程環境邁出的重要一步,但一些棘手的問題仍然存在。其中主要是不同的語言有不同的類型系統。Ruby的字符串是可修改的,而Java的不可修改。Scala把所有東西都當成對象,即便是在Java裡作為原始類型的實體也是如此。

處理這些差異,並為同一JVM內的不同語言提供更好的交互和互操作方式,是目前尚未解決的問題,也是正在積極處理有望近期解決的問題。

想像一個將來要做的Web應用:其核心部分可能是Java代碼,Web部分是用Compojure寫的(即Clojure),所用的JSON處理類庫是用純粹的JavaScript寫的,而你想用ScalaTest中一些很酷的TDD功能來對它進行測試。

這形成了一個JavaScript、Clojure、Scala和Java彼此之間都會直接調用的局面。對JVM語言能夠互操作並以一種標準的方式調用彼此對象的需求會隨著時間逐漸增強。社區內的廣泛共識是需要一種元對像協議(Metaobject Protocol,MOP),以便所有這些語言都能以一種標準的方式工作。MOP可以看做是一種在代碼內描述特定的語言如何實現面向對象及相關問題的辦法。

要實現這一目標,我們需要想想那些能讓某種語言中的對象能在另外一種語言中使用的辦法。一種簡單的方式是把它轉換成其他語言中的本地類型(或甚至在外部運行時中創建一個新的「影子」對像)。這種辦法簡單,但有嚴重的問題:

  • 所有語言必須都有一個通用的「主」接口(或超類),語言內的所有類型都必須實現它(比如JRuby中的IRubyObject);
  • 如果用影子對象,那會增加很多內存分配,性能也會受影響。

相反,我們可以考慮為外部運行時構建一個服務作為入口。這一服務會提供一個接口,某一運行時可以通過該接口對外部運行時中的對象執行標準操作,比如:

  • 在其他語言運行時中創建一個新對象並返回對它的引用;
  • 訪問(獲取方法或設置方法)外部對象的屬性;
  • 調用外部對像上的方法,並返回結果;
  • 將外部對像轉換成不同的相關類型;
  • 訪問外部對象的其他能力,對一些語言來說可能和方法調用的語義有所不同。

在這樣的系統中,可以通過在外部運行時上調用navigator來訪問外部方法或屬性。調用者需要提供一種辦法來標識要訪問的方法:someMethod。通常是個字符串,但某些情況下也可能是MethodHandle

navigator.callMethod(someObject, someMethod, param1, param2, ...);
  

要讓這種辦法起作用,所有協作語言運行時中的navigator接口必須都一樣。實際上,語言之間的真實聯繫很可能是用invokedynamic建立起來的。

接下來我們去看看多語言JVM和Java 8的模塊化子系統組合起來是個什麼樣子。

14.2.2 多語言模塊化

隨著Jigsaw和平台模塊化的出現,不僅僅是Java才會從模塊化中受益(並需要參與進來)。其他語言也能加入其中有所表現。

可以想像,navigator接口及其輔助類很可能會成為一個模塊,對某一非Java語言運行時的支持將會由一個或多個模塊實現。圖14-2中展示了這一模塊系統看起來是什麼樣子。

圖14-2 實現了多語言解決方案的模塊

如你所見,我們可以用模塊系統搭建包含多種語言的應用程序。Clojure模塊提供基本的Clojure平台,Compojure模塊引入運行webapp所需的組件,包括特定版本的JAR,在別處運行時這些JAR可能會用不同的版本。Scala及其XML也出現了,為了實現Scala和Clojure之間的互操作,Navigator模塊也出現了。

在下一節中,我們會討論非Java語言在平台上的爆炸性湧現所推動的另一個編程趨勢:並發。