NO IMAGE

    3 月 21 日,作為世界上使用最廣泛程式語言之一的 Java 迎來了第十個大版本。在 2017 年,甲骨文曾宣佈,Java 語言將每隔 6 個月提供一次更新,並承諾不會跳票,Java 10 正是在此規則下的首個大版本。需要注意的是 Java 9 和 Java 10 都不是 LTS 版本。和過去的 Java 大版本升級不同,這兩個只有半年左右的開發和維護期。而未來的 Java 11,也就是 18.9 LTS,才是 Java 8 之後第一個 LTS 版本(得到 Oracle 等商業公司的長期支援服務)。

Java 10 新特性

這次釋出的 Java 10,新帶來的特性並不多。

根據官網公開資料,共有 12 個 JEP(JDK Enhancement Proposal 特性加強提議),帶來以下加強功能:

  1. JEP286,var 區域性變數型別推斷。

  2. JEP296,將原來用 Mercurial 管理的眾多 JDK 倉庫程式碼,合併到一個倉庫中,簡化開發和管理過程。

  3. JEP304,統一的垃圾回收介面。

  4. JEP307,G1 垃圾回收器的並行完整垃圾回收,實現並行性來改善最壞情況下的延遲。

  5. JEP310,應用程式類資料 (AppCDS) 共享,通過跨程序共享通用類後設資料來減少記憶體佔用空間,和減少啟動時間。

  6. JEP312,ThreadLocal 握手互動。在不進入到全域性 JVM 安全點 (Safepoint) 的情況下,對執行緒執行回撥。優化可以只停止單個執行緒,而不是停全部執行緒或一個都不停。

  7. JEP313,移除 JDK 中附帶的 javah 工具。可以使用 javac -h 代替。

  8. JEP314,使用附加的 Unicode 語言標記擴充套件。

  9. JEP317,能將堆記憶體佔用分配給使用者指定的備用記憶體裝置。

  10. JEP317,使用 Graal 基於 Java 的編譯器,可以預先把 Java 程式碼編譯成原生代碼來提升效能。

  11. JEP318,在 OpenJDK 中提供一組預設的根證書頒發機構證書。開源目前 Oracle 提供的的 Java SE 的根證書,這樣 OpenJDK 對開發人員使用起來更方便。

  12. JEP322,基於時間定義的釋出版本,即上述提到的釋出週期。版本號為\$FEATURE.\$INTERIM.\$UPDATE.\$PATCH,分別是大版本,中間版本,升級包和補丁版本。

部分新特性解析

1,迄今為止,在官方放出了Java 10少數新特性裡面,區域性變數型別推斷(local-variable type inference) 絕對是備受萬眾矚目的。它將我們常常在JS裡面使用的var 變數引入到語言特性中,把我們從那些冗長的變數宣告中解放出來。

這個語言功能在其他一些語言 (C#、JavaScript) 和基於 JRE 的一些語言 (Scala 和 Kotlin) 中,早已被加入。

在 Java 語言很早就在考慮,早在 2016 年正式提交了 JEP286 提議。後來舉行了一次公開的開發者調查,獲得最多建議的是採用類似 Scala 的方案,“同時使用 val 和 var”,約佔一半;第二多的是“只使用 var”,約佔四分之一。後來 Oracle 公司經過慎重考慮,採用了只使用 var 關鍵字的方案。

有了這個功能,開發者在寫這樣的程式碼時:

List<String> myList = new ArrayList<String>()

可以省去前面的型別宣告,而只需要

var list = new ArrayList<String>()

編譯器會自動推斷出 list 變數的型別。對於鏈式表示式來說,也會很方便:

var stream = blocks.stream();

使用範圍:區域性變數。更加確切的說法是:具有初始化器的區域性型別變數宣告。

2,應用程式類資料共享(AppCDS)

CDS 特性在原來的 bootstrap 類基礎之上,擴充套件加入了應用類的 CDS(Application Class-Data Sharing) 支援。

其原理為:在啟動時記錄載入類的過程,寫入到文字檔案中,再次啟動時直接讀取此啟動文字並載入。設想如果應用環境沒有大的變化,啟動速度就會得到提升。

我們可以想像為類似於作業系統的休眠過程,合上電腦時把當前應用環境寫入磁碟,再次使用時就可以快速恢復環境。

我在自己 PC 電腦上做以下應用啟動實驗。

首先部署 wildfly 12 應用伺服器,採用 JDK10 預覽版作為 Java 環境。另外需要用到一個工具 cl4cds[1],作用是把載入類的日誌記錄,轉換為 AppCDS 可以識別的格式。

A、安裝好 wildfly 並部署一個應用,具有 Angularjs, rest, jpa 完整應用技術棧,預熱後啟動三次,並記錄完成部署時間

分別為 6716ms, 6702ms, 6613ms,平均時間為 6677ms。

B、加入環境變數並啟動,匯出啟動類日誌

export PREPEND_JAVA_OPTS=”-Xlog:class load=debug:file=/tmp/wildfly.classtrace”

C、使用 cl4cds 工具,生成 AppCDS 可以識別的 cls 格式

/jdk-10/bin/java -cp src/classes/ io.simonis.cl4cds /tmp/wildfly.classtrace /tmp/wildfly.cls

開啟檔案可以看到內容為:

java/lang/Object id: 0x0000000100000eb0

java/io/Serializable id: 0x0000000100001090

java/lang/Comparable id: 0x0000000100001268

java/lang/CharSequence id: 0x0000000100001440

……

org/hibernate/type/AssociationType id: 0x0000000100c61208 super: 0x0000000100000eb0 interfaces: 0x0000000100a00d10 source: /home/shihang/work/jboss/wildfly/dist/target/wildfly-12.0.0.Final/modules/system/layers/base/org/hibernate/main/hibernate-core-5.1.10.Final.jar

org/hibernate/type/AbstractType id: 0x0000000100c613e0 super: 0x0000000100000eb0 interfaces: 0x0000000100a00d10 source: /home/shihang/work/jboss/wildfly/dist/target/wildfly-12.0.0.Final/modules/system/layers/base/org/hibernate/main/hibernate-core-5.1.10.Final.jar

org/hibernate/type/AnyType id: 0x0000000100c61820 super: 0x0000000100c613e0 interfaces: 0x0000000100c61030 0x0000000100c61208 source: /home/shihang/work/jboss/wildfly/dist/target/wildfly-12.0.0.Final/modules/system/layers/base/org/hibernate/main/hibernate-core-5.1.10.Final.jar

….

這個檔案用於標記類的載入資訊。

D、使用環境變數啟動 wildfly,模擬啟動過程並匯出 jsa 檔案,就是記錄了啟動時類的資訊。

export PREPEND_JAVA_OPTS=”-Xshare:dump -XX: UseAppCDS -XX:SharedClassListFile=/tmp/wildfly.cls -XX: UnlockDiagnosticVMOptions -XX:SharedArchiveFile=/tmp/wildfly.jsa”

檢視產生的檔案資訊,jsa 檔案有較大的體積。

/opt/work/cl4cds$ ls -l /tmp/wildfly.*

-rw-rw-r– 1 shihang shihang  8413843 Mar 20 11:07 /tmp/wildfly.classtrace

-rw-rw-r– 1 shihang shihang  4132654 Mar 20 11:11 /tmp/wildfly.cls

-r–r–r– 1 shihang shihang 177659904 Mar 20 11:13 /tmp/wildfly.jsa

E、使用 jsa 檔案啟動應用伺服器

export PREPEND_JAVA_OPTS=”-Xshare:on -XX: UseAppCDS -XX: UnlockDiagnosticVMOptions -XX:SharedArchiveFile=/tmp/wildfly.jsa”

啟動完畢後記錄時長,三次分別是 5535ms, 5333ms, 5225ms,平均為 5364ms,相比之前的 6677ms 可以算出啟動時間提升了 20% 左右。

這個效率提升,對於雲端應用部署很有價值。