Mark Reinhold談“Java9及其未來”

infoq發表於2015-03-27

  Reinhold作了主題為“Java9及其未來”的演講,他分享了即將到來的在Java 9中的功能和Java生態系統未來的一些計劃。

  Java 9的一個主要變化是引入了收錄在JEP200之中的Java模組系統。此舉意在提供模組化的JDK,當執行無需整個環境的應用時,只需載入相對較小的程式碼量,一如Mark所言:列印Hello World不應依賴CORBA。有了模組化,Java虛擬機器的原始碼佈局(JEP201)、各個Java元件,以及執行時映象(JEP220)都將結束與各種不同目的的模組綁在一起的歷史。java.base將成為核心層,是否要引入其他模組,比如java.logging和java.sql(包含了java.sql和javax.sql包)將視情況而定。

  模組自身可以表達它們之間的依賴關係,但是包還是要從模組中匯出以便為他人使用。由於內部的具體實現,一些包(如java.base模組中的sun.reflect*包)對朋友包(如java.logging和java.sql包)可見,但對普通的Java程式碼不可見。依賴關係有傳遞性,所以依賴java.sql包的程式碼自動繼承對java.logging的依賴,一如在Eclipse bundles中使用Require-Bundle操作。做安全檢查時,將執行java.lang.SecurityManager::checkPackageAccess,以確保在執行時檢查該模組的邊界。

  模組化意味著清除無處不在的rt.jar(曾經取代了Java 1.1中的classes.zip),以及通過建立配置檔案(profile)來減少JVM的體積。包含了java.base模組java.lang包和其他一些包的compact1 profile大小為11Mb,在此基礎上增加了RMI和XML的compact2是17Mb,再加上java.naming、java.management和java.sql的compact3是30Mb。完整的JRE仍然可以使用55Mb的選項,JDK擴充套件了到了150Mb。模組化還將導致去除擴充套件類路徑和重組一些庫路徑(具體來說,要將*.properties從lib/資料夾移動到conf/這個新的目錄下)。

  系統類處理程式從jar協議更改為jrt協議(Java執行時),這將影響到程式碼的編寫。通過定義模組,可以從rt.jar中載入指定的類。因此,jar:file:/path/to/rt.jar!java/lang/Class.class的引用將被jrt:/java.base/java.lang.Class.class代替。這些是ClassLoader.getSystemResource()方法呼叫者的實現細節,該方法一直返回一個不透明的URL,但對JAR檔案或檔案系統有假定關係的程式碼將因此而被破壞。工具(整合開發環境,如Eclipse和IntelliJ )中導航到rt.jar的做法,需要使用新的機制導航到模組;我們已經有了新的FileSystem類,可以執行基於路徑的訪問:FileSystem.getFileSystem("jrt:/"),瀏覽所有可用的模組及其內容。

  可以使用jlink將這些模組連結到一個執行時,jlink是Java 9中的新工具,用來構建一個只包含執行所需的依賴的自定義映象。言下之意是,這將是一個靜態的連結選項,提供單一的可執行檔案(Google的Go語言就是這麼做的)。

  模組化後終於可以去除*.internal.*和sun.*包了。雖然我們的程式碼從未直接使用這些包,但是因為此前缺乏內部包之間的邊界,導致會在程式碼庫中不經意間地使用它們。比如sun.misc.BASE64Encoder和sun.misc.BASE64Decoder類的標準對應類是java.util.Base64.Encoderjava.util.Base64.Decoder。從Java 8開始可用的工具jdeps,會展示現有檔案的內部類依賴,Java 9還將指明哪些模組被使用了。

 預見未來

  Mark Reinhold還討論了未來有可能加入JVM的功能,比如值型別(結構體)和值型別(如值型別或原生型別)的泛型增強。這些何時加入還都沒有時間表,但是思考和調研會促進這些功能在未來的某一時刻加入的可能性。Mark Reinhold還討論了未來有可能加入JVM的功能,比如值型別(結構體)和值型別(如值型別或原生型別)的泛型增強。這些何時加入還都沒有時間表,但是思考和調研將會促進這些功能在未來的某一時刻加入的可能性。

  值型別是一種代表資料的固定結構,就像一個類。然而與類(引用)不同,JVM的實現允許直接在堆疊或在陣列中、一個連續的記憶體佈局上優化資料結構。這改進了對資料結構的訪問,更重要的是改進了CPU的效能,CPU可以從連續的記憶體中載入一塊資料,而不再使用分佈在堆上的指標陣列。實現有可能是這樣的:

value /* final */ class Point {
   int x;
   int y;
   Point(int x, int y) { this.x = x; this.y = y } 
}  

  值型別預設是final的,因此資料結構需要在建立時完全初始化。JIT可以通過對方法呼叫優化傳遞值,而不是在不必要時也複製。值型別可以有方法,也可以實現介面(潛在地,繼承其他值型別),但是不能被引用,所以不能用null做比較。值型別可用於實現其它類原生型別,比如int128、Complex或Tuple。

  為了實現值型別的泛型,我們需要做些改變;例如,ArrayList包含remove(int index)方法和remove(T value)方法。使用int型別來泛化將導致方法衝突並引起錯誤。雖然引入新的方法removeAt(int index)能解決這個問題,但是需要匯出才能使現有的型別繼續使用現有的方法(非值型別)。一種可能的方法是使用條件編譯,可以使用類似'where ref T { }'這樣的條件編譯塊,從而匯出引用型別而不是值型別。Valhalla專案正在研究如何將這兩個概念在未來共存,但是目前仍處於研究階段。

  Mark Reinhold還簡要講述了Panama專案,這是一個旨在改進使用Java外部函式介面呼叫Java原生程式碼效能的專案。Java外部函式介面收錄在JEP191中,是基於JRuby的已有實現 JNAJNR 提出的。他最後總結說,Java在不斷演化,並有節奏地定位大問題:在Java 5中引入泛型,在Java 8中引入lambda表示式,並在Java 9中引入模組化,它像鐳射一樣聚焦於向後相容性,以免破壞已經存在的程式碼或客戶。

  英文原文:Mark Reinhold on Java 9 and Beyond

相關文章