北京時(shí)間 3 月 21 日誊爹,Oracle 官方宣布 Java 10 正式發(fā)布天吓。這是 Java 大版本周期變化后的第一個(gè)正式發(fā)布版本(詳見這里)蘸际,非常值得關(guān)注祭陷。你可以點(diǎn)擊以下地址即刻下載:
http://www.oracle.com/technetwork/java/javase/downloads/index.html
去年 9 月苍凛,Oracle 將 Java 大版本周期從原來的 2-3 年,調(diào)整成每半年發(fā)布一個(gè)大的版本兵志。而版本號(hào)仍延續(xù)原來的序號(hào)醇蝴,即 Java 8、Java 9想罕、Java 10悠栓、Java 11.....
但和之前不一樣的是霉涨,同時(shí)還有一個(gè)版本號(hào)來表示發(fā)布的時(shí)間和是否為 LTS(長(zhǎng)期支持版本),比如 Java 10 對(duì)應(yīng) 18.3惭适。如下示例:
/jdk-10/bin$ ./java -version
openjdk version "10" 2018-03-20
OpenJDK Runtime Environment 18.3 (build 10+46)
OpenJDK 64-Bit Server VM 18.3 (build 10+46, mixed mode)
需要注意的是 Java 9 和 Java 10 都不是 LTS 版本笙瑟。和過去的 Java 大版本升級(jí)不同,這兩個(gè)只有半年左右的開發(fā)和維護(hù)期癞志。而未來的 Java 11往枷,也就是 18.9 LTS,才是 Java 8 之后第一個(gè) LTS 版本(得到 Oracle 等商業(yè)公司的長(zhǎng)期支持服務(wù))凄杯。
這種發(fā)布模式已經(jīng)得到了廣泛應(yīng)用错洁,一個(gè)成功的例子就是 Ubuntu Linux 操作系統(tǒng),在偶數(shù)年 4 月的發(fā)行版本為 LTS戒突,會(huì)有很長(zhǎng)時(shí)間的支持屯碴。如 2014 年 4 月份發(fā)布的 14.04 LTS,Canonical 公司和社區(qū)支持到 2019 年膊存。類似的导而,Node.js,Linux kernel隔崎,F(xiàn)irefox 也采用類似的發(fā)布方式今艺。
Java 未來的發(fā)布周期,將每半年發(fā)布一個(gè)大版本仍稀,每個(gè)季度發(fā)布一個(gè)中間特性版本洼滚。這樣可以把一些關(guān)鍵特性盡早合并入 JDK 之中埂息,快速得到開發(fā)者反饋技潘,可以在一定程度上避免 Java 9 兩次被迫推遲發(fā)布日期的尷尬。
下圖為 2017 年 JavaOne 大會(huì)時(shí)千康,Oracle 公開的未來 Java 版本發(fā)布和支持周期圖享幽。
Java 10 新特性
這次發(fā)布的 Java 10,新帶來的特性并不多拾弃。
根據(jù)官網(wǎng)公開資料值桩,共有 12 個(gè) JEP(JDK Enhancement Proposal 特性加強(qiáng)提議),帶來以下加強(qiáng)功能:
JEP286豪椿,var 局部變量類型推斷奔坟。
JEP296,將原來用 Mercurial 管理的眾多 JDK 倉(cāng)庫(kù)代碼搭盾,合并到一個(gè)倉(cāng)庫(kù)中咳秉,簡(jiǎn)化開發(fā)和管理過程。
JEP304鸯隅,統(tǒng)一的垃圾回收接口澜建。
JEP307,G1 垃圾回收器的并行完整垃圾回收,實(shí)現(xiàn)并行性來改善最壞情況下的延遲炕舵。
JEP310何之,應(yīng)用程序類數(shù)據(jù) (AppCDS) 共享,通過跨進(jìn)程共享通用類元數(shù)據(jù)來減少內(nèi)存占用空間咽筋,和減少啟動(dòng)時(shí)間溶推。
JEP312,ThreadLocal 握手交互奸攻。在不進(jìn)入到全局 JVM 安全點(diǎn) (Safepoint) 的情況下悼潭,對(duì)線程執(zhí)行回調(diào)。優(yōu)化可以只停止單個(gè)線程舞箍,而不是停全部線程或一個(gè)都不停舰褪。
JEP313,移除 JDK 中附帶的 javah 工具疏橄≌寂模可以使用 javac -h 代替。
JEP314捎迫,使用附加的 Unicode 語言標(biāo)記擴(kuò)展晃酒。
JEP317,能將堆內(nèi)存占用分配給用戶指定的備用內(nèi)存設(shè)備窄绒。
JEP317贝次,使用 Graal 基于 Java 的編譯器,可以預(yù)先把 Java 代碼編譯成本地代碼來提升效能彰导。
JEP318蛔翅,在 OpenJDK 中提供一組默認(rèn)的根證書頒發(fā)機(jī)構(gòu)證書。開源目前 Oracle 提供的的 Java SE 的根證書位谋,這樣 OpenJDK 對(duì)開發(fā)人員使用起來更方便山析。
JEP322,基于時(shí)間定義的發(fā)布版本掏父,即上述提到的發(fā)布周期笋轨。版本號(hào)為\$FEATURE.\$INTERIM.\$UPDATE.\$PATCH,分別是大版本赊淑,中間版本爵政,升級(jí)包和補(bǔ)丁版本。
部分特性說明
1. var 類型推斷陶缺。
這個(gè)語言功能在其他一些語言 (C#钾挟、JavaScript) 和基于 JRE 的一些語言 (Scala 和 Kotlin) 中,早已被加入组哩。
在 Java 語言很早就在考慮等龙,早在 2016 年正式提交了 JEP286 提議处渣。后來舉行了一次公開的開發(fā)者調(diào)查,獲得最多建議的是采用類似 Scala 的方案蛛砰,“同時(shí)使用 val 和 var”罐栈,約占一半;第二多的是“只使用 var”泥畅,約占四分之一荠诬。后來 Oracle 公司經(jīng)過慎重考慮,采用了只使用 var 關(guān)鍵字的方案位仁。
有了這個(gè)功能柑贞,開發(fā)者在寫這樣的代碼時(shí):
ArrayList myList = new ArrayList()
可以省去前面的類型聲明,而只需要
var list = new ArrayList()
編譯器會(huì)自動(dòng)推斷出 list 變量的類型聂抢。對(duì)于鏈?zhǔn)奖磉_(dá)式來說钧嘶,也會(huì)很方便:
var stream = blocks.stream();
...
int maxWeight = stream.filter(b -> b.getColor() == BLUE)
? ? ? ? ? ? ? ? ? ? ?.mapToInt(Block::getWeight)
? ? ? ? ? ? ? ? ? ? ?.max();
開發(fā)者無須聲明并且 import 引入 Stream 類型,只用 stream 作為中間變量琳疏,用 var 關(guān)鍵字使得開發(fā)效率提升有决。
不過 var 的使用有眾多限制,包括不能用于推斷方法參數(shù)類型空盼,只能用于局部變量书幕,如方法塊中,而不能用于類變量的聲明揽趾,等等台汇。
另外,我個(gè)人認(rèn)為篱瞎,對(duì)于開發(fā)者而言苟呐,變量類型明顯的聲明會(huì)提供更加全面的程序語言信息,對(duì)于理解并維護(hù)代碼有很大的幫助奔缠。一旦 var 被廣泛運(yùn)用掠抬,開發(fā)者閱讀三方代碼而沒有 IDE 的支持下吼野,會(huì)對(duì)程序的流程執(zhí)行理解造成一定的障礙校哎。所以我建議盡量寫清楚變量類型,程序的易讀維護(hù)性有時(shí)更重要一些瞳步。
2. 統(tǒng)一的 GC 接口
在 JDK10 的代碼中闷哆,路徑為 openjdk/src/hotspot/share/gc/,各個(gè) GC 實(shí)現(xiàn)共享依賴 shared 代碼单起,GC 包括目前默認(rèn)的 G1抱怔,也有經(jīng)典的 Serial、Parallel嘀倒、CMS 等 GC 實(shí)現(xiàn)屈留。
3. 應(yīng)用程序類數(shù)據(jù)(AppCDS)共享
CDS 特性在原來的 bootstrap 類基礎(chǔ)之上局冰,擴(kuò)展加入了應(yīng)用類的 CDS(Application Class-Data Sharing) 支持。
其原理為:在啟動(dòng)時(shí)記錄加載類的過程灌危,寫入到文本文件中康二,再次啟動(dòng)時(shí)直接讀取此啟動(dòng)文本并加載。設(shè)想如果應(yīng)用環(huán)境沒有大的變化勇蝙,啟動(dòng)速度就會(huì)得到提升沫勿。
我們可以想像為類似于操作系統(tǒng)的休眠過程闯传,合上電腦時(shí)把當(dāng)前應(yīng)用環(huán)境寫入磁盤令境,再次使用時(shí)就可以快速恢復(fù)環(huán)境八毯。
我在自己 PC 電腦上做以下應(yīng)用啟動(dòng)實(shí)驗(yàn)辜王。
首先部署 wildfly 12 應(yīng)用服務(wù)器翩活,采用 JDK10 預(yù)覽版作為 Java 環(huán)境逮刨。另外需要用到一個(gè)工具 cl4cds[1]踱侣,作用是把加載類的日志記錄埠戳,轉(zhuǎn)換為 AppCDS 可以識(shí)別的格式馆衔。
A时甚、安裝好 wildfly 并部署一個(gè)應(yīng)用,具有 Angularjs, rest, jpa 完整應(yīng)用技術(shù)棧哈踱,預(yù)熱后啟動(dòng)三次荒适,并記錄完成部署時(shí)間
分別為 6716ms, 6702ms, 6613ms,平均時(shí)間為 6677ms开镣。
B刀诬、加入環(huán)境變量并啟動(dòng),導(dǎo)出啟動(dòng)類日志
export PREPEND_JAVA_OPTS="-Xlog:class+load=debug:file=/tmp/wildfly.classtrace"
C邪财、使用 cl4cds 工具陕壹,生成 AppCDS 可以識(shí)別的 cls 格式
/jdk-10/bin/java -cp src/classes/ io.simonis.cl4cds /tmp/wildfly.classtrace /tmp/wildfly.cls
打開文件可以看到內(nèi)容為:
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
....
這個(gè)文件用于標(biāo)記類的加載信息。
D树埠、使用環(huán)境變量啟動(dòng) wildfly糠馆,模擬啟動(dòng)過程并導(dǎo)出 jsa 文件,就是記錄了啟動(dòng)時(shí)類的信息怎憋。
export PREPEND_JAVA_OPTS="-Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=/tmp/wildfly.cls -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=/tmp/wildfly.jsa"
查看產(chǎn)生的文件信息又碌,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 文件啟動(dòng)應(yīng)用服務(wù)器
export PREPEND_JAVA_OPTS="-Xshare:on -XX:+UseAppCDS -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=/tmp/wildfly.jsa"
啟動(dòng)完畢后記錄時(shí)長(zhǎng)毕匀,三次分別是 5535ms, 5333ms, 5225ms,平均為 5364ms癌别,相比之前的 6677ms 可以算出啟動(dòng)時(shí)間提升了 20% 左右皂岔。
這個(gè)效率提升,對(duì)于云端應(yīng)用部署很有價(jià)值展姐。
以上實(shí)驗(yàn)方法參考于技術(shù)博客 [2]躁垛。
4. JEP314剖毯,使用附加的 Unicode 語言標(biāo)記擴(kuò)展。
JDK10 對(duì)于 Unicode BCP 47 有了更多的支持教馆,BCP 47 是 IETF 定義語言集的規(guī)范文檔速兔。使用擴(kuò)展標(biāo)記,可以更方便的獲得所需要的語言地域環(huán)境活玲。
如 JDK10 加入的一個(gè)方法涣狗,
java.time.format.DateTimeFormatter::localizedBy
通過這個(gè)方法,可以采用某種數(shù)字樣式舒憾,區(qū)域定義或者時(shí)區(qū)來獲得時(shí)間信息所需的語言地域本地環(huán)境信息镀钓。
附:從鏈接 [3] 可以看到 JDK10 所有的方法級(jí)別改動(dòng)。
5. 查看當(dāng)前 JDK 管理根證書镀迂。
自 JDK9 起在 keytool 中加入?yún)?shù) -cacerts丁溅,可以查看當(dāng)前 JDK 管理的根證書。而 OpenJDK9 中 cacerts 為空探遵,這樣就會(huì)給開發(fā)者帶來很多不變窟赏。
EP318 就是利用 Oracle 開源出 Oracle JavaSE 中的 cacerts 信息,在 OpenJDK 中提供一組默認(rèn)的根證書頒發(fā)機(jī)構(gòu)證書箱季,目前有 80 條記錄涯穷。
/jdk-10/bin$ ./keytool -list -cacerts
Enter keystore password: ?
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 80 entries
verisignclass2g2ca [jdk], Dec 2, 2017, trustedCertEntry,
Certificate fingerprint (SHA-256): 3A:43:E2:20:FE:7F:3E:A9:65:3D:1E:21:74:2E:AC:2B:75:C2:0F:D8:98:03:05:BC:50:2C:AF:8C:2D:9B:41:A1
......
下一版本展望
下一個(gè) Java 大版本會(huì)是 Java 11,也是 Java 8 之后的 LTS 版本藏雏,預(yù)計(jì)會(huì)在今年的 9 月份發(fā)布拷况。目前只有四個(gè) JEP,更多加強(qiáng)提議會(huì)逐步加入掘殴。
這個(gè)版本會(huì)充分發(fā)揮模塊化的能力赚瘦,把當(dāng)前 JDK 中的關(guān)于 JavaEE 和 Corba 的部分移除,變得更加緊湊奏寨。
雖然 JDK9 最大的亮點(diǎn)是模塊化起意,但 Java 業(yè)界廣泛接納并且適應(yīng)需要一個(gè)過程。當(dāng)前已經(jīng)有一些支持模塊化的類庫(kù)病瞳,如 log4j2揽咕,但大多數(shù)還未支持。
可以預(yù)見 JDK11 發(fā)布之后仍源,模塊化特性就成為長(zhǎng)期支持特性心褐,會(huì)有越來越多的類庫(kù)提供對(duì)模塊化的支持。
Java 依然會(huì)是最適合應(yīng)用開發(fā)的語言和平臺(tái)笼踩,龐大的社區(qū)和廣泛的開發(fā)者,會(huì)不斷促使 Java 不斷完善優(yōu)化亡嫌,在各個(gè)編程領(lǐng)域繼續(xù)發(fā)揚(yáng)光大嚎于。
對(duì)文中引用文章原作者表示致謝掘而!引用的圖示,數(shù)據(jù)和方法都屬于原作者于购。
[1]: https://simonis.github.io/cl4cds/
[2]: https://marschall.github.io/2018/02/18/wildfly-appcds.html
[3]: https://gunnarmorling.github.io/jdk-api-diff/jdk9-jdk10-api-diff.html#java.time.format.DateTimeFormatter
想要了解更多程序員資訊的袍睡,可以關(guān)注我。