JDK16 GA 正式發(fā)布: 17個(gè)特性,一網(wǎng)打盡,可能是東半球最快解讀!
就在昨天,JDK16 GA正式發(fā)布:
- 2020/12/10 Rampdown Phase One (fork from main line)
- 2021/01/14 Rampdown Phase Two
- 2021/02/04 Initial Release Candidate
- 2021/02/18 Final Release Candidate
- 2021/03/16 General Availability
官方給出的JDK16所有特性一覽如下,總計(jì)17個(gè)特性:
- 338: Vector API (Incubator)
- 347: Enable C++14 Language Features
- 357: Migrate from Mercurial to Git
- 369: Migrate to GitHub
- 376: ZGC: Concurrent Thread-Stack Processing
- 380: Unix-Domain Socket Channels
- 386: Alpine Linux Port
- 387: Elastic Metaspace
- 388: Windows/AArch64 Port
- 389: Foreign Linker API (Incubator)
- 390: Warnings for Value-Based Classes
- 392: Packaging Tool
- 393: Foreign-Memory Access API (Third Incubator)
- 394: Pattern Matching for instanceof
- 395: Records
- 396: Strongly Encapsulate JDK Internals by Default
- 397: Sealed Classes (Second Preview)
接下來(lái),我們一一對(duì)其進(jìn)行解讀。
338: Vector API
Java提供了一些Vector API, 那到底什么是Vector API呢?廢話不多說(shuō),給你舉個(gè)例子。我們先寫(xiě)一段普通的Java代碼:
- void scalarComputation(float[] a, float[] b, float[] c) {
- for (int i = 0; i < a.length; i++) {
- c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
- }
- }
那么,用Vector API實(shí)現(xiàn)等價(jià)邏輯的代碼如下所示。是不是更復(fù)雜了, CRY~圖片,嗯,沒(méi)關(guān)系,反正要用到Vector API起碼得是10年以后的事情了:
- static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;
- void vectorComputation(float[] a, float[] b, float[] c) {
- for (int i = 0; i < a.length; i += SPECIES.length()) {
- var m = SPECIES.indexInRange(i, a.length);
- // FloatVector va, vb, vc;
- var va = FloatVector.fromArray(SPECIES, a, i, m);
- var vb = FloatVector.fromArray(SPECIES, b, i, m);
- var vc = va.mul(va).
- add(vb.mul(vb)).
- neg();
- vc.intoArray(c, i, m);
- }
- }
347: Enable C++14 Language Features
一句話概括就是JDK16的C++源碼可以使用C++14的語(yǔ)法特性。并且如果在HotSpot源碼中確實(shí)有用到的話,會(huì)給出這些特性的特殊指導(dǎo)說(shuō)明。
369: Migrate to GitHub
OpenJDK終于也遷移到GitHub中,這個(gè)和 JEP 357: Migrate from Mercurial to Git 一起完成的。之前OpenJDK的源代碼都是用Mercuial維護(hù)的,沒(méi)聽(tīng)說(shuō)過(guò)?沒(méi)聽(tīng)說(shuō)過(guò)就對(duì)了,也不用浪費(fèi)時(shí)間去了解。
OpenJDK還解釋了為什么選擇GitHub,主要有3個(gè)原因:
- 相比其他產(chǎn)品,GitHub的性能更好。
- GitHub是全球最大的源碼托管服務(wù),并且有超過(guò)5kw用戶。
- GitHub擁有最多用于擴(kuò)展的API。這些API支撐了很多文本編輯器(例如: Emacs, VS Code, Atom等), IDE工具(IDEA, Eclipse等), 命令行等對(duì)它的支持。
最后,附上GitHub中OpenJDK項(xiàng)目地址:https://github.com/openjdk/。
376: ZGC: Concurrent Thread-Stack Processing
這個(gè)需求的意思是ZGC把線程棧處理從safepoint挪到并發(fā)階段,從而減少GC的停頓時(shí)間。ZGC的目標(biāo)就是消滅GC停頓和擴(kuò)展性問(wèn)題。為此,ZGC做了很多的工作,在把Thread-Stack從safepoint挪到并發(fā)階段之前,還有很多其他的GC操作也做了這些優(yōu)化,比如:marking, relocation, reference processing, class unloading, 以及大多數(shù)的 root processing。
386: Alpine Linux Port
支持一些新的平臺(tái),比如Alpine Linux。Alpine Linux是一個(gè)Linux發(fā)行版, 它是一個(gè)由社區(qū)開(kāi)發(fā)的Linux操作系統(tǒng),該操作系統(tǒng)以安全為理念,面向x86路由器、防火墻、虛擬專(zhuān)用網(wǎng)、IP電話盒及服務(wù)器而設(shè)計(jì)。官方用3個(gè)詞來(lái)介紹它:Small. Simple. Secure。確實(shí)很小,它的發(fā)行包不到6MB。
此外,JEP 388: Windows/AArch64 Port 也是類(lèi)似的特性,即支持Windows平臺(tái)和ARM64(AArch64)平臺(tái)。
392: Packaging Tool
這個(gè)特性在JDK14中已經(jīng)被介紹過(guò)(JEP 343),它的目的是創(chuàng)建一個(gè)打包工具jpackage,jpackage將Java應(yīng)用程序打包到特定平臺(tái)的程序包中,該程序包包含所有必需的依賴項(xiàng)。該應(yīng)用程序可以作為普通JAR文件的集合或作為模塊的集合提供。受支持的特定平臺(tái)的軟件包格式有:Linux: deb and rpm macOS: pkg and dmg Windows: msi and exe
打包命令參考如下:
- $ jpackage --name myapp --input lib --main-jar main.jar
- # 如果MANIFEST.MF中沒(méi)有Main-Class,也可以使用如下的打包命令
- $ jpackage --name myapp --input lib --main-jar main.jar \
- --main-class myapp.Main
393: Foreign-Memory Access API
引入API允許Java程序安全的、高效的訪問(wèn)堆外內(nèi)存。這個(gè)需求的目標(biāo)是希望做到如下幾點(diǎn):
- Generality: 通用性,一個(gè)簡(jiǎn)單的API就可以操作很多外部?jī)?nèi)存,例如本地內(nèi)存、托管的堆內(nèi)存等。
- Safety: 安全性, 這些API不會(huì)破壞JVM的安全,可以放心的使用。
- Control: 可控性,客戶端應(yīng)具有關(guān)于如何顯示或者隱式控制重新分配內(nèi)存段的選項(xiàng)。
- Usability: 可用性, 對(duì)那些需要訪問(wèn)堆外內(nèi)的程序來(lái)說(shuō),比如使用Unsafe接口操作堆外內(nèi)存,新設(shè)計(jì)的API應(yīng)該是更好的替代者。
JDK16將這些API放到孵化的名為jdk.incubator.foreign的模塊中,有3個(gè)主要的抽象: MemorySegment, MemoryAddress 和 MemoryLayout。
394: Pattern Matching for instanceof
這個(gè)特性最先出現(xiàn)在JDK14中(JEP 305), JDK15中(JEP 375)是第二輪預(yù)覽。此次加到JDK16中是徹底完成這個(gè)特性。這個(gè)特性是為了增強(qiáng)Java語(yǔ)法,允許在instanceof中加入表達(dá)式匹配。以前我們寫(xiě)代碼可能需要這樣:
- if (obj instanceof String) {
- String s = (String) obj; // grr...
- ...
- }
現(xiàn)在我們只需要這樣:
- if (obj instanceof String s) {
- // Let pattern matching do the work!
- ...
- }
我們還可以這樣:
- if (obj instanceof String s && s.length() > 5) {
- flag = s.contains("jdk");
- }
395: Records
很多人抱怨Java太冗余了,很多代碼太形式主義了。比如如下這段代碼所示,除了x和y的屬性定義,其他的構(gòu)造方法,equals、hashCode、toString方法基本上都借助IDE工具生成:
- class Point {
- private final int x;
- private final int y;
- Point(int x, int y) {
- this.x = x;
- this.y = y;
- }
- int x() { return x; }
- int y() { return y; }
- public boolean equals(Object o) {
- if (!(o instanceof Point)) return false;
- Point other = (Point) o;
- return other.x == x && other.y == y;
- }
- public int hashCode() {
- return Objects.hash(x, y);
- }
- public String toString() {
- return String.format("Point[x=%d, y=%d]", x, y);
- }
- }
因此Java發(fā)明了一種新的Java類(lèi),我們只需要簡(jiǎn)單的幾行代碼即可。有點(diǎn)類(lèi)似于lombok給我們代碼帶來(lái)的簡(jiǎn)潔性:
- record Point(int x, int y) { }
397: Sealed Classes
中文翻譯的含義是密封類(lèi),具體是什么意思呢?舉個(gè)栗子,如下這段代碼所示,Expr這個(gè)接口用sealed進(jìn)行了修飾,那么只有permits后面的實(shí)現(xiàn)類(lèi)實(shí)現(xiàn)這個(gè)接口,不允許其他實(shí)現(xiàn)類(lèi):
- package com.example.expression;
- public sealed interface Expr
- permits ConstantExpr, PlusExpr, TimesExpr, NegExpr { ... }
- public final class ConstantExpr implements Expr { ... }
- public final class PlusExpr implements Expr { ... }
- public final class TimesExpr implements Expr { ... }
- public final class NegExpr implements Expr { ... }
sealed不僅可以修飾interface,也可以修飾類(lèi)class。JEP 397 的目的是限制接口的實(shí)現(xiàn),以及限制類(lèi)的繼承。如此一來(lái),類(lèi)和接口的作者對(duì)其寫(xiě)的類(lèi)和接口有更好的控制權(quán)。
sealed修飾的類(lèi)有3大約束:
- sealed修飾的類(lèi)和它permits的子類(lèi)必屬屬于相同的module(JDK9中的模塊化)。如果是沒(méi)有命名的module,那么需要在相同的包名下。
- 每一個(gè)permits的子類(lèi)必須直接實(shí)現(xiàn)sealed的類(lèi),而不能間接實(shí)現(xiàn)。
- 每一個(gè)permits的子類(lèi)必須用一個(gè)修飾符描述它是如何傳播從父類(lèi)繼承過(guò)來(lái)的密封性的。比如子類(lèi)用final修飾,表示不允許其他類(lèi)繼承。再比如用sealed修飾,從而繼續(xù)限制子類(lèi)的子類(lèi)。
本文轉(zhuǎn)載自微信公眾號(hào)「阿飛的博客」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系阿飛的博客公眾號(hào)。