JDK14新特性
- Pattern Matching for instanceof (Preview)
- Non-Volatile Mapped Byte Buffers (Incubator)
- Helpful NullPointerExceptions
- Switch Expressions (Standard)
- Packaging Tool (Incubator)
- NUMA-Aware Memory Allocation for G1
- JFR Event Streaming
- Records (Preview)
- Deprecate the Solaris and SPARC Ports
- Remove the Concurrent Mark Sweep (CMS) Garbage Collector
- ZGC on macOS (experimental)
- ZGC on Windows (experimental)
- Deprecate the ParallelScavenge + SerialOld GC Combination
- Remove the Pack200 Tools and API
- Text Blocks (Second Preview)
- Foreign-Memory Access API (Incubator)
2020年3月17日,Java 14(Java SE 14)及其Java開發工具包14(JDK 14)開源發佈。本文主要記錄了JDK14的16個新特性。
本文的IDE爲IDEA2020.1,JDK14是通過IDE下載的Open JDK.
Pattern Matching for instanceof (Preview)
instanceof的模式匹配(預覽版)
String s = "instance";
//before jdk14
if (s instanceof String) {
String str = s;
System.out.println("before jdk14:" + str);
}
//in jdk14
if (s instanceof String str) {
System.out.println("before jdk14:" + str);
}
if (s instanceof String str && str.equals("instance")) {
System.out.println("TRUE");
}
僅當object不爲null時,instanceOf纔會匹配,然後僅將其分配給str。 在instanceof中使用模式匹配應減少Java程序中顯式強制轉換的總數。
Non-Volatile Mapped Byte Buffers (Incubator)
新增了java.base/jdk/internal/misc/ExtendedMapMode.java以支持MappedByteBuffer訪問non-volatile
memory (NVM)。
從JDK1.4開始,Java引入了NIO文件相關的API,帶有MappedByteBuffer的FileChannel將文件數據的一部分加載到虛擬內存中,然後引入了稱爲Path的新增強功能。 當我們使用Java NIO時,Path是一個接口,它將java.io.File類替換爲文件或目錄的表示形式。
現在,Java 14對MappedByteBuffer進行了增強,以將部分文件數據加載到非易失性內存(NVM)中。 非易失性存儲器或非易失性存儲器是計算機存儲器,即使關閉電源(例如ROM(只讀存儲器),閃存,硬盤等存儲設備)也不會丟失/刪除數據。 如果像RAM一樣關閉電源,則無法保留數據。 唯一需要的API更改是FileChannel客戶端採用的新枚舉,以請求映射位於NVM支持的文件系統而不是傳統文件存儲系統上的文件。
Helpful NullPointerExceptions
JVM生成的NullPointerExceptions(NPE)異常消息的改進。可以更好地提示哪個地方出現的空指針,需要通過-XX:+ShowCodeDetailsInExceptionMessages開啓。 對於程序過早終止,這將對開發人員和支持人員有幫助的信息。 由於NPE幾乎可以出現在程序中的任何位置,因此嘗試捕獲它們並從中恢復通常是不切實際的。
//NullPointerExceptions
pojo p = new pojo(null);
System.out.println(p.getApple().getColor());
在此之前,報錯時這樣的:
現在在運行參數中配置:-XX:+ShowCodeDetailsInExceptionMessages,開啓Helpful NullPointerExceptions:
開啓之後,運行結果是這樣的:
如圖所示,準確的告知了我們哪個變量爲null。
Switch Expressions (Standard)
JDK14擴展了switch語句,在JDK12種已引入,在JDK14中變爲了正式版。現在的case中使用->來替代以前的:+break,而且提供了yield來在block中返回值;
//switch
//before JDK14
Calendar calendar = Calendar.getInstance();
Integer today = calendar.get(Calendar.DAY_OF_WEEK);
String weekday = "";
switch (today) {
case Calendar.MONDAY:
case Calendar.TUESDAY:
case Calendar.WEDNESDAY:
case Calendar.THURSDAY:
case Calendar.FRIDAY:
weekday = "weekday";
break;
case Calendar.SATURDAY:
case Calendar.SUNDAY:
weekday = "weekend";
break;
default:
throw new IllegalStateException("Unexpected value: " + today);
}
System.out.println("Before JDK14:"+weekday);
//in JDK14
weekday = switch (today) {
case Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY -> "weekday";
case Calendar.SATURDAY, Calendar.SUNDAY -> "weekend";
default -> {
yield "unknown";
//throw new IllegalStateException("Unexpected value: " + Calendar.DAY_OF_WEEK);
}
};
System.out.println("JDK14:"+weekday);
Packaging Tool (Incubator)
打包工具(孵化中)
JDK14引入了jdk.incubator.jpackage.jmod,它基於JavaFX javapackager tool構建,目的在於創建一個簡單的打包工具。
jpackage工具將Java應用程序捆綁到特定於平臺的程序包中,其中包含所需的所有依賴項。作爲一組普通的JAR文件或作爲模塊的集合。
可以用於構建以下文件格式的安裝文件:
- Linux: deb and rpm
- macOS: pkg and dmg
- Windows: msi and exe
非模塊化的app的構建示例如下:
jpackage --name myapp --input lib --main-jar main.jar
NUMA-Aware Memory Allocation for G1
NUMA-Aware Memory Allocation(NUMA)是一種將微處理器集羣配置爲多處理系統的方法,因此可以在本地共享內存,可以提高性能並擴展系統的功能。
Java 14提供了可識別NUMA的內存分配功能,以提高大型計算機上的G1性能。
G1的堆組織爲固定大小區域的集合。一個區域通常是一組物理頁面,儘管使用大頁面(通過-XX:+ UseLargePages)時,多個區域可能組成一個物理頁面。
如果指定了+ XX:+ UseNUMA選項,則在初始化JVM時,區域將平均分佈在可用NUMA節點的總數上。
JFR Event Streaming
JDK11引入了JFR,使用的時候先dump到磁盤上然後再分析;而在JDK14則支持stream方式來進行進程內和進程外應用程序的持續性監控。
Records (Preview)
JDK14引入了預覽版本的record類型。在開發中,我們需要編寫許多重複代碼,編寫簡單的實體類:構造函數,getter 和 setter,equals(),hashCode(),toString()等。爲避免這種重複代碼,Java計劃使用Records。
在此前的實體類:
而在JDK14的預覽版中,只需一行代碼就可以實現等同於以上的效果。
讓我們來看看編譯後的AppleRecord實體類,它長這樣:
可以看到AppleRecord繼承了java.lang.Record,而且生成了final的hashCode()及equals()方法,但是卻沒有了setter方法,getter方法也省略了get前綴。
Deprecate the Solaris and SPARC Ports
廢棄Solaris / SPARC,Solaris / x64和Linux / SPARC端口,以便將來刪除。
通過取消對這些端口的支持,OpenJDK社區中的貢獻者將能夠加速新功能的開發,以推動平臺向前發展。
構建配置更改
以下內容會導致嘗試配置Solaris和/或SPARC:
$ bash ./configure
...
checking compilation type... native
configure: error: The Solaris and SPARC ports are deprecated and may be removed in a future release. \
Use --enable-deprecated-ports=yes to suppress this error.
configure exiting with result code 1
$
新的–enable-deprecated-ports = yes 配置項將消除該錯誤並繼續。
$ bash ./configure --enable-deprecated-ports=yes
...
checking compilation type... native
configure: WARNING: The Solaris and SPARC ports are deprecated and may be removed in a future release.
...
Build performance summary:
* Cores to use: 32
* Memory limit: 96601 MB
爲Solaris和SPARC(包括Solaris / SPARC,Solaris / x64,Linux / SPARC)配置構建時,將發出錯誤/警告。
Remove the Concurrent Mark Sweep (CMS) Garbage Collector
移除了CMS垃圾收集器。此更新將停用CMS編譯,從源樹中刪除gc / cms目錄的內容,並刪除僅CMS選項。如果在JDK14中使用-XX:+UseConcMarkSweepGC的話,會出現警告,但是不會退出而是以默認的垃圾收集器運行。
ZGC on macOS (experimental)
之前的ZGC只能在linux上使用,現在mac上也能使用了。
ZGC on Windows (experimental)
之前的ZGC只能在linux上使用,現在windows(不能低於1803版本)上也能使用。
Deprecate the ParallelScavenge + SerialOld GC Combination
廢棄了parallel young generation GC與SerialOld GC的組合( -XX:+UseParallelGC與-XX:-UseParallelOldGC配合開啓),現在使用-XX:+UseParallelGC -XX:-UseParallelOldGC或者-XX:-UseParallelOldGC都會出現告警。
Remove the Pack200 Tools and API
移除了Pack200 API。
Text Blocks (Second Preview)
在Java中,要將HTML,XML,SQL或JSON代碼片段嵌入到代碼中通常很難閱讀且難以保留,並且爲了克服此問題,Java 14引入了Text Block。
JDK13引入的text blocks進行第二輪預覽,JDK14的版本主要增加了兩個escape sequences,分別是 <line-terminator>與\s escape sequence。
由三個英文雙引號(""")開始/結束。與字符串文字中的字符不同,內容可以直接包含雙引號字符。 允許在文本塊中使用\“,但不是必需的或不建議使用。"""可以使字符可以不轉義出現,並且還可以從視覺上區分文本塊和字符串文字。
//HTML without text block
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
//HTML with text block
String htmlTextBlock = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
Foreign-Memory Access API (Incubator)
提供了孵化版本的API用於操縱堆外內存。