OpenJDK項目Valhall發布了一項重大更新,宣布了JVM值類型中一些初步的、尚處于極早期階段的設計概念。
該項目的主要任務是“研究、孵化高級的Java JVM及語言的候選特性”。Brian Goetz解釋了該項目的主要目標:
使JVM的內存分配模型與現代硬件的成本模型相一致; 擴展泛型,允許對所有的類型進行抽象,包括基本類型、值,甚至是void; 使現有的庫,尤其是JDK,在演化的過程中保持兼容性,從而可以充分利用這些特性。一直到版本9,包括版本9在內,Java只有兩種類型的值——基本類型和對象引用。換句話說,Java環境有意不提供內存分配的底層控制。舉例來說,這意味著Java沒有類似結構這樣的東西,任何復合數據類型都只能通過引用訪問。
這種內存分配模式在過去的20年里一直在發揮作用,是Java平臺內存分配的主要實現模式。它的優點是非常簡單,但伴隨著大量的性能權衡,例如,對象數組的處理就涉及不可避免的間接尋址和隨之而來的緩存未命中。
因此,許多性能導向的程序員會喜歡定義可以更高效分配內存的類型——值類型。
在這些新類型中,復合數據的每個數據項不需要有一個完整的對象頭,這可以降低開銷。消除對象頭也同時消除了當前所有Java對象都具有的特定于實例的元數據。
這種方法的其中一個后果是對象標識會丟失,當且僅當所有字段都相等時值才相等。這使得值類型有和基本類型類似的行為——值的每一個副本根本就沒有自己的標識。
為了順應這一重大變化,需要引入一些新的字節碼,但是目前,據說只需要新增2個操作碼:
vdefault會為特定的值類生成默認實例; withfield為值類型生成一個新值(及拋出無效值)部分已有的字節碼也需要進行一些修改來處理值類型。
在VM層面上也需要做一些工作,以便核心庫在演化過程中可以保持兼容性——例如,現在已經可以在方法中測試Object變量,看它是否真的包含值對象。
除了值類型這個簡單的概念外,當前還有一些更深層次的設計問題。例如,值類型是否可以用作泛型類型的類型參數值?
如果不可以,那么這似乎會極大的限制值類型的使用。因此,有關值類型的設計討論總是假設它們可以用作尚未確定的泛型增強形式的類型參數值。
Valhalla項目正在進行中的研究產生了以下尚處于早期階段的設計概念。在VM層面應該有三種不同類型的JVM類及接口類型:
引用類型表示類實例的引用,該實例有一個標識(或者為空); 值類型包含沒有標識的值類實例; 通用類型可以是其他兩種類型中的任意一種。這里有一個顯而易見的問題——“應該如何理解現有類文件中的類型信息?”
也就是說,Java 9類文件中現有的對象類型究竟應該視為引用類型還是通用類型?這是只是個簡單的例子,我們之前從未見過值類的實例。
當前的設計尚處于非常早期的階段,還只是一個尚需數月才能成熟的提案,到生產就緒及代碼交付可能還需要數年。
由于發布計劃不斷變化,現在還不能完全確定哪個Java版本最終會把值類型作為生產特性。
在Valhalla項目郵件列表上,相關的討論、研究還在繼續,對VM內部構件感興趣的讀者可以從那里了解更多細節,從中可以了解到,當前的工作距離供大多數開發人員使用還有很長的路,該項目僅是原型階段。
查看英文原文:Design of Java Value Types Makes Progress