Java SE 13 新增特性
Java SE 13 新增特性
作者:Grey
原文地址:Java SE 13 新增特性
源碼
鏡像倉庫: GitCode:java_new_features
新版 Switch 使用方式
switch
語句增加了 yield 關鍵字表示返回值,這個特性在Java SE 13
中是預覽特性,在Java SE 14
正式引入。程式碼如下:
註:如果你用Java SE 12
運行上述程式碼,需要指定--enable-preview
參數,如果使用 Intellij IDEA ,參考How to Enable Java Preview Features and Run Code from IntelliJ IDEA
package git.snippets.jdk13;
/**
* switch yield功能
* jdk13 實驗性功能
* 到jdk14 正式使用
* @author <a href="mailto:[email protected]">Grey</a>
* @date 2021/11/29
* @since 13
*/
public class SwitchYield {
public static void main(String[] args) {
String t = test("apple");
System.out.println(t);
String m = test("abc");
System.out.println(m);
}
private static String test(String c) {
return switch (c) {
case "apple", "Apple":
yield "蘋果";
case "banana":
yield "香蕉";
default:
yield "無法識別";
};
}
}
輸出結果
蘋果
無法識別
文本塊(預覽功能)
為了定義一個多行字元串,我們習慣於使用轉義序列來處理字元串中包含的換行和雙引號。例如,一個SQL語句看起來像這樣
String sql =
"SELECT id, firstName, lastName FROM Employee\n"
+ "WHERE departmentId = \"IT\"\n"
+ "ORDER BY lastName, firstName";
String content = "{\n"
+ " \"upperSummary\": null,\n"
+ " \"sensitiveTypeList\": null,\n"
+ " \"gmtModified\": \"2011-08-05 10:50:09\",\n"
+ " \"lowerGraph\": null,\n"
+ " \"signature\": \"\",\n"
+ " \"appName\": \"xxx\",\n"
+ " \"lowerSummary\": null,\n"
+ " \"gmtCreate\": \"2011-08-05 10:50:09\",\n"
+ " \"type\": \"CALL\",\n"
+ " \"name\": \"xxxx\",\n"
+ " \"subType\": \"yyy\",\n"
+ " \"id\": 1,\n"
+ " \"projectId\": 1,\n"
+ " \"status\": 1\n"
+ "}";
JDK Enhancement Proposal 355允許我們以更可讀的方式編寫這樣的字元串。
String sql = """
SELECT id, firstName, lastName FROM Employee
WHERE departmentId = "IT"
ORDER BY lastName, firstName""";
String content2 = """
{
"upperSummary": null,
"sensitiveTypeList": null,
"gmtModified": "2011-08-05 10:50:09",
"lowerGraph": null,
"signature": "",
"appName": "xxx",
"lowerSummary": null,
"gmtCreate": "2011-08-05 10:50:09",
"type": "CALL",
"name": "xxxx",
"subType": "yyy",
"id": 1,
"projectId": 1,
"status": 1
}
""";
文本塊在Java SE 13
屬於預覽功能,在Java SE 15
中正式啟用
Socket API 新實現方式
java.net.Socket 和 java.net.ServerSocket 類早在 Java 1.0 時就已經引入了,它們的實現的 Java 程式碼和 C 語言程式碼的混合,維護和調試都十分不易;而且這個實現還存在並發問題,有時候排查起來也很困難。
因此,在 Java 13 中引入了新的實現方式,使用了新的實現 NioSocketImpl 來代替老舊的 PlainSocketImpl 實現。用戶隨時可以通過 -Djdk.net.usePlainSocketImpl 參數切換回老的實現方式,以兼容意外情況。程式碼如下
package git.snippets.jdk13;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 新版Socket API 使用了新的實現 NioSocketImpl 來代替老舊的 PlainSocketImpl 實現。
* 需要增加-XX:+TraceClassLoading參數
*
* @author <a href="mailto:[email protected]">Grey</a>
* @date 2022/8/20
* @since 13
*/
public class NewSocketAPI {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(8000)) {
boolean running = true;
while (running) {
Socket clientSocket = serverSocket.accept();
//do something with clientSocket
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用 Java 13 運行,通過參數 -XX:+TraceClassLoading 追蹤載入的類,日誌中可以看到 NioSocketImpl。
[0.099s][info ][class,load] java.util.Properties$LineReader source: shared objects file
[0.099s][info ][class,load] java.io.FileInputStream$1 source: shared objects file
[0.100s][info ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.100s][info ][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base
[0.100s][info ][class,load] sun.nio.ch.NativeDispatcher source: jrt:/java.base
[0.100s][info ][class,load] sun.nio.ch.SocketDispatcher source: jrt:/java.base
但在 Java 12 並不是 NioSocketImpl。
[0.120s][info ][class,load] java.util.concurrent.ConcurrentSkipListMap$Node source: shared objects file
[0.120s][info ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.120s][info ][class,load] java.net.AbstractPlainSocketImpl source: jrt:/java.base
[0.120s][info ][class,load] java.net.PlainSocketImpl source: jrt:/java.base
[0.120s][info ][class,load] java.net.SocksSocketImpl source: jrt:/java.base
ZGC: 取消提交未使用的記憶體
ZGC 是 Java SE 11 中引入的一個實驗性垃圾收集器,它承諾在10毫秒或更短的時間內實現 stop-the-world 。
JDK Enhancement Proposal 351擴展了 ZGC 的功能,以便在特定時間後將未使用的堆記憶體返回給作業系統。
使用-XX:ZUncommitDelay
,你可以指定ZGC返回未使用記憶體的時間,單位是秒。默認情況下,這個值是300秒。
該功能默認是啟用的,可以用-XX:-ZUncommit
來禁用。
ZGC 將在 Java SE 15 中達到生產狀態。
動態 CDS 檔案
Java SE 10 中引入了應用類數據共享–一個允許創建所謂共享存檔文件的功能。這個文件包含了所使用平台的 JVM 所要求的二進位形式的應用類。該文件通過記憶體映射的 I/O 映射到 JVM 的記憶體中。
直到現在,創建這個文件還相對複雜。首先,我們必須在應用程式的測試運行期間轉儲一個類列表。只有在第二步,我們才能從這個列表中生成共享檔案。
java -Xshare:off -XX:+UseAppCDS
-XX:DumpLoadedClassList=helloworld.lst
-cp target/helloworld.jar eu.happycoders.appcds.Main
java -Xshare:dump -XX:+UseAppCDS
-XX:SharedClassListFile=helloworld.lst
-XX:SharedArchiveFile=helloworld.jsa
-cp target/helloworld.jar
JDK Enhancement Proposal 350簡化了這個過程。從 Java SE 13 開始,你可以指定-XX:ArchiveClassesAtExit
參數,在應用程式執行結束時生成共享存檔。不再需要額外的參數-Xshare:on
和-XX:+UseAppCDS
了。
java -XX:ArchiveClassesAtExit=helloworld.jsa
-cp target/helloworld.jar eu.happycoders.appcds.Main
創建的共享存檔也比以前小得多。因為它現在只包含應用程式的類。
從 Java SE 13 開始,共享存檔的使用方法如下。
java -XX:SharedArchiveFile=helloworld.jsa
-cp target/helloworld.jar eu.happycoders.appcds.Main
更多
參考資料
official Java 13 Release Notes
Java 13 Features (with Examples)
Java ByteBuffer Example: How to Use flip() and compact()
Application Class-Data Sharing