Valhalla項目:了解Java史詩級重構(gòu)
譯文?譯者 | 李睿
審校 | 孫淑娟?
在Java中,除了int這樣的原語之外,所有的事物都是對象。事實證明,這一設置對Java產(chǎn)生了巨大的影響,這些年來,這種影響越來越大。這個看似微不足道的設計決策會在集合和泛型等關鍵領域引起問題。它還限制了某些性能優(yōu)化。Java語言重構(gòu)項目Valhalla旨在糾正這些問題。Valhalla項目負責人Brian Goetz表示,Valhalla將“彌合原語類和對象之間的裂痕”。?
可以說,Valhalla項目是一次史詩級的重構(gòu),旨在解決自Java誕生以來一直隱藏在平臺中的技術債務。這種徹底的進化證明了Java不僅是經(jīng)典,而且仍然處于編程語言設計的前沿。以下了解Valhalla項目的關鍵技術組件,以及為什么它們對Java的未來如此重要。 ?
Java中的性能問題 ?
當Java在上世紀90年代首次引入時,決定所有用戶創(chuàng)建的類型都是類。只有少數(shù)原語類被當作特殊類型。它們不是作為基于指針的類結(jié)構(gòu)處理的,而是直接映射到操作系統(tǒng)類型。8種原語類型是int、byte、short、long、float、double、boolean和char。?
直接將這些變量映射到操作系統(tǒng)對性能來說更好,因為數(shù)值操作在去掉對象的引用開銷時性能更好。而且,所有數(shù)據(jù)最終在程序中都解析為這8種基本類型。類只是一種結(jié)構(gòu)和組織層,它提供了更強大的處理基本類型的方法。另一種結(jié)構(gòu)是數(shù)組。原語、類和數(shù)組構(gòu)成了Java表達能力的全部范圍。 ?
但是原語是與類和數(shù)組不同的,程序員已經(jīng)學會了直觀地處理這些差異。例如,原語是按值傳遞,而對象是按引用傳遞。其中的原因相當深刻,這歸結(jié)為身份的問題??梢哉f,原語值是可替換的:intx=4是整數(shù)4,無論它出現(xiàn)在哪里??梢栽趀quals()vs==中看到這種區(qū)別,前者測試對象的值等價性,后者測試對象的同一性。如果兩個引用在內(nèi)存中共享相同的空間,它們滿足==,這意味著它們是同一個對象。任何設置為4的int類型也滿足==,而int類型根本不支持.equals()。 ?
Java虛擬機(JVM)可以利用處理原語的方式來優(yōu)化存儲、檢索和操作原語的方式。特別是,如果平臺確定一個變量沒有改變(也就是說,它是常數(shù)或不可變的),那么就可以對其進行優(yōu)化。 ?
相比之下,對象則不適合這種優(yōu)化,因為它們有一個身份。作為類的實例,對象所保存的數(shù)據(jù)既可以是原語,也可以是其他類。對象本身用一個指針句柄來尋址。這就創(chuàng)建了一個引用網(wǎng)絡:對象圖。每當某個值被更改時(或者即使它可能被更改),JVM都必須維護對象的最終記錄以供參考。需要引用對象是一些性能優(yōu)化的障礙。?
性能上的困難還不止于此。對象作為引用桶的特性意味著它們以一種非常松散的方式存在于內(nèi)存中。Fluffy是一個技術術語,用來描述JVM無法壓縮對象以最小化其內(nèi)存占用這一事實。當一個對象有對另一個對象的引用作為其組成的一部分時,JVM被迫維護該指針關系。(在某些情況下,巧妙的優(yōu)化可以幫助確定嵌套引用是特定實體的唯一句柄。) ?
在他撰寫的一篇博客文章中,Goetz使用了一系列點來說明引用的非密集性,可以使用類。假設有一個Landmark類,它有一個名稱和一個地理位置字段。這意味著一個像圖1所示的內(nèi)存結(jié)構(gòu): ?
圖1 Java對象的“蓬松”內(nèi)存占用
想要實現(xiàn)的是在適當?shù)臅r候保存對象的能力,如圖2所示:?
圖2. 內(nèi)存中密集的對象?
這就是早期設計決策對Java平臺的性能挑戰(zhàn)的概述。以下考慮這些決策如何在三個關鍵領域影響性能。 ?
問題1:方法調(diào)用和傳遞值 ?
內(nèi)存中對象的默認結(jié)構(gòu)對于內(nèi)存和緩存來說都是低效的。此外,還有機會在方法調(diào)用約定方面取得進展。能夠?qū)粗嫡{(diào)用參數(shù)傳遞給具有類語法的方法(在適當?shù)那闆r下)將帶來更高性能和好處。?
問題2:箱子和自動裝箱?
除了低效率之外,原語和類之間的區(qū)別還帶來了語言級的困難。創(chuàng)建像Integer和Long這樣的原語“箱”(以及自動裝箱)是為了減輕這種區(qū)別所帶來的問題。但是,它并不能真正解決這些問題,而且它給開發(fā)人員和機器都帶來了一定程度的開銷。作為開發(fā)人員,必須了解并記住int和Integer(以及ArrayList<Integer>, int[], Integer[],以及缺少ArrayList<int>)之間的區(qū)別。與此同時,機器必須在兩者之間進行轉(zhuǎn)換。?
在某種程度上,裝箱模糊了這些實體如何工作的底層細微差別,因此很難同時了解類語法的強大功能和原語的性能。?
問題3:泛型和流?
在泛型中,所有這些考慮因素都非常重要。泛型旨在使跨功能的泛化更容易、更顯式,但這組非對象變量(原語)的挑剔存在只會導致它崩潰。<int>不存在,因為int根本不是一個類,它不是對象的后代。?
這個問題在集合和流等庫中也有體現(xiàn),通過提供IntStream和其他非泛型變體,泛型庫函數(shù)的理想被迫處理int與Integer、long與long等現(xiàn)實。?
Valhalla的解決方案:值類和原語類?
Valhalla計劃從根本上解決這些問題。第一個也是最基本的概念是值類。這里的思想是,可以定義一個類,它具有類的所有優(yōu)點,比如具有方法并能夠?qū)崿F(xiàn)泛型,但沒有標識。在實踐中,這意味著類是不可變的,不能是布局多態(tài)的(其中超類可以通過抽象屬性對子類進行操作)。?
值類為人們提供了一種清晰而明確的方式來獲得所追求的性能特征,同時仍然可以訪問類語法和獲得行為的好處。這意味著庫構(gòu)建者也可以使用它們,從而改進API設計。?
更進一步的是原語類,它類似于一個更極端的值類。本質(zhì)上,原語類是一個真正的原語變量的薄包裝器,但帶有類方法。這有點像自定義的流線型原語箱。改進在于使裝箱系統(tǒng)更加顯式和可擴展。此外,由原語類包裝的原語值保留了原語的性能特征(沒有底層的裝箱和拆箱)。因此,原語類可以在任何類可以存在的地方使用——例如,在Object[]數(shù)組中?;绢愋筒荒転榭?它們不能被設置為空)。?
一般來說,Valhalla項目使原語和用戶定義類型更加接近。這為開發(fā)人員在純原語和對象之間提供了更多的選擇,并使權(quán)衡變得明確。它還使這些操作總體上更加一致。特別是,新的原語系統(tǒng)將使原語和對象的工作方式、它們的裝箱方式以及如何添加新的原語和對象變得更加流暢。?
Java的語法將如何變化?
Valhalla已經(jīng)看到了一些不同的語法建議,但現(xiàn)在項目有了明確的形式和方向。兩個新的關鍵字修改了類關鍵字:value和primitive。用value class語法聲明的類將放棄其標識,并在這一過程中獲得性能改進。除了可變性和多態(tài)限制外,對類的大部分期望仍然適用,并且此類類可以完全參與泛型代碼(例如object[]或ArrayList<T>)。值類默認為null。?
原語類語法創(chuàng)建的類比傳統(tǒng)對象和傳統(tǒng)原語更進一步。這些類默認為字段的基礎值(int為0,double為0.0,等等),并且不能為空。原語類在優(yōu)化方面獲得最多,在特性方面犧牲最多。原語類最終將被用于對平臺中的所有原語建模,這意味著用戶和庫定義的原語添加將與內(nèi)置組件參與到同一個系統(tǒng)中。?
IdentityObject和ValueObject?
IdentityObject和ValueObject是Valhalla項目中引入的兩個新接口。這將允許運行時確定正在處理的類的類型。 ?
對于有經(jīng)驗的Java開發(fā)人員來說,最根本的語法更改可能是增加了.ref成員。所有類型現(xiàn)在都有V.ref()字段。這個字段的操作類似于基本類型上的box,所以是int.ref類似于用Integer包裝int。普通類將解析.ref到它們的引用??傮w效果是提供了一種一致的方式來請求變量的引用,而不管變量的類型是什么。這也會導致所有Java數(shù)組都是“協(xié)變的”,也就是說,它們都起源于Object[]。因此,int[]現(xiàn)在來自Object[],可以在任何需要的地方使用。 ?
結(jié)論?
值類和原語類將對Java及其生態(tài)系統(tǒng)產(chǎn)生重大影響。當前的路線圖計劃首先引入值類,然后是原語類。接下來將遷移現(xiàn)有的原語裝箱類(如Integer)以使用新的原語類。有了這些特性,下一個被稱為通用泛型的特性將允許原語類直接與泛型一起使用,從而消除API中重用的許多復雜性。最后,專門的泛型(允許T擴展Foo的所有表達能力)將與原語類集成。 ?
Valhalla項目及其組成項目仍處于設計階段,但越來越接近。項目周圍的活動表明,價值類很快就會出現(xiàn)在JDK預覽中。?
在這些有趣的技術工作之外,讓人感覺到了Java的持續(xù)活力。人們有意愿也有能力去識別平臺在哪些方面可以從根本上進行改進,這是保持Java相關性的真正承諾的證據(jù)。而Project Loom是對Java未來持樂觀態(tài)度的另一個項目。?
原文標題:??Project Valhalla: A look inside Java’s epic refactor??,作者:Matthew Tyson
?