Java 13 中的新功能
Java 13已于 2019 年 9 月 17 日正式发布,请在此处下载 Java 13或此openJDK 存档。
Java 13 特性。
- 1. JEP 350 动态 CDS 档案
- 2. JEP 351 ZGC:取消提交未使用的内存
- 3. JEP-353 重新实现 Legacy Socket API
- 4. JEP-354 开关表达式(预览)
- 5. JEP-355 文本块(预览)
Java 13 开发人员功能。
切换表达式(预览)、文本块或多行(预览)
1. JEP 350 动态 CDS 档案
Java 10 引入了JEP 310 应用程序类数据共享。此 JEP 简化了创建 CDS 档案的过程。
此命令创建一个 CDS 存档文件.jar
。
$ java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
此命令.jar
使用现有的 CDS 存档运行。
$ bin/java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello
类数据共享 (CDS) 通过创建一次类数据存档并重用它来提高启动性能,这样 JVM 就不需要再次重新创建它。
进一步阅读
2. JEP 351 ZGC:取消提交未使用的内存
Java 11 引入了JEP 333: Z Garbage Collector (Experimental);它在清理堆内存时提供了短暂的暂停时间。然而,它并没有将未使用的堆内存返还给操作系统,即使它很长时间没有使用。
该 JEP 通过将未使用的堆内存返回给操作系统来增强 ZGC。
进一步阅读
3. JEP-353 重新实现 Legacy Socket API
的底层实现java.net.Socket
和java.net.ServerSocket
古追溯到JDK 1.0的遗留Java和C代码的混合,是很难维护和调试。此 JEP 为 Socket API 引入了新的底层实现,这是 Java 13 中的默认实现。
在 Java 13 之前,它使用PlainSocketImpl
forSocketImpl
public class ServerSocket implements java.io.Closeable {
/**
* The implementation of this Socket.
*/
private SocketImpl impl;
}
Java 13 引入了一个新NioSocketImpl
类作为PlainSocketImpl
. 但是,如果出现问题,我们仍然可以PlainSocketImpl
通过设置jdk.net.usePlainSocketImpl
系统属性切换回旧的实现。
查看一个简单的 Socket 示例。
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class JEP353 {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(8888)){
boolean running = true;
while(running){
Socket clientSocket = serverSocket.accept();
//do something with clientSocket
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
在 Java 13 中,默认实现是 NioSocketImpl
D:\test>javac JEP353.java
D:\test>java JEP353
D:\test>java -XX:+TraceClassLoading JEP353 | findStr Socket
[0.040s][info ][class,load] java.net.ServerSocket source: jrt:/java.base
[0.040s][info ][class,load] jdk.internal.access.JavaNetSocketAccess source: jrt:/java.base
[0.040s][info ][class,load] java.net.ServerSocket$1 source: jrt:/java.base
[0.040s][info ][class,load] java.net.SocketOptions source: jrt:/java.base
[0.040s][info ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.044s][info ][class,load] java.net.SocketImpl$$Lambda$1/0x0000000800ba0840 source: java.net.SocketImpl
[0.047s][info ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.047s][info ][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base
[0.047s][info ][class,load] sun.nio.ch.SocketDispatcher source: jrt:/java.base
[0.052s][info ][class,load] java.net.SocketAddress source: jrt:/java.base
[0.052s][info ][class,load] java.net.InetSocketAddress source: jrt:/java.base
[0.052s][info ][class,load] java.net.InetSocketAddress$InetSocketAddressHolder source: jrt:/java.base
[0.053s][info ][class,load] sun.net.ext.ExtendedSocketOptions source: jrt:/java.base
[0.053s][info ][class,load] jdk.net.ExtendedSocketOptions source: jrt:/jdk.net
[0.053s][info ][class,load] java.net.SocketOption source: jrt:/java.base
[0.053s][info ][class,load] jdk.net.ExtendedSocketOptions$ExtSocketOption source: jrt:/jdk.net
[0.053s][info ][class,load] jdk.net.SocketFlow source: jrt:/jdk.net
[0.053s][info ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions source: jrt:/jdk.net
[0.053s][info ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions$1 source: jrt:/jdk.net
[0.054s][info ][class,load] jdk.net.ExtendedSocketOptions$1 source: jrt:/jdk.net
[0.054s][info ][class,load] sun.nio.ch.NioSocketImpl$FileDescriptorCloser source: jrt:/java.base
[0.055s][info ][class,load] java.net.Socket source: jrt:/java.base
我们可以PlainSocketImpl
通过设置Djdk.net.usePlainSocketImpl
系统属性来切换回。
D:\test>java -Djdk.net.usePlainSocketImpl -XX:+TraceClassLoading JEP353 | findStr Socket
[0.041s][info ][class,load] java.net.ServerSocket source: jrt:/java.base
[0.041s][info ][class,load] jdk.internal.access.JavaNetSocketAccess source: jrt:/java.base
[0.041s][info ][class,load] java.net.ServerSocket$1 source: jrt:/java.base
[0.041s][info ][class,load] java.net.SocketOptions source: jrt:/java.base
[0.041s][info ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.045s][info ][class,load] java.net.SocketImpl$$Lambda$1/0x0000000800ba0840 source: java.net.SocketImpl
[0.048s][info ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.048s][info ][class,load] java.net.AbstractPlainSocketImpl source: jrt:/java.base
[0.048s][info ][class,load] java.net.PlainSocketImpl source: jrt:/java.base
[0.048s][info ][class,load] java.net.AbstractPlainSocketImpl$1 source: jrt:/java.base
[0.050s][info ][class,load] sun.net.ext.ExtendedSocketOptions source: jrt:/java.base
[0.050s][info ][class,load] jdk.net.ExtendedSocketOptions source: jrt:/jdk.net
[0.050s][info ][class,load] java.net.SocketOption source: jrt:/java.base
[0.051s][info ][class,load] jdk.net.ExtendedSocketOptions$ExtSocketOption source: jrt:/jdk.net
[0.051s][info ][class,load] jdk.net.SocketFlow source: jrt:/jdk.net
[0.051s][info ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions source: jrt:/jdk.net
[0.051s][info ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions$1 source: jrt:/jdk.net
[0.051s][info ][class,load] jdk.net.ExtendedSocketOptions$1 source: jrt:/jdk.net
[0.051s][info ][class,load] java.net.StandardSocketOptions source: jrt:/java.base
[0.051s][info ][class,load] java.net.StandardSocketOptions$StdSocketOption source: jrt:/java.base
[0.053s][info ][class,load] sun.net.ext.ExtendedSocketOptions$$Lambda$2/0x0000000800ba1040 source: sun.net.ext.ExtendedSocketOptions
[0.056s][info ][class,load] java.net.SocketAddress source: jrt:/java.base
[0.056s][info ][class,load] java.net.InetSocketAddress source: jrt:/java.base
[0.058s][info ][class,load] java.net.InetSocketAddress$InetSocketAddressHolder source: jrt:/java.base
[0.059s][info ][class,load] java.net.SocketCleanable source: jrt:/java.base
PS Java的15 JEP 373:重新实现传统DatagramSocket的API,取代的底层实现java.net.DatagramSocket
和java.net.MulticastSocket
。
进一步阅读
4. JEP-354 开关表达式(预览)
Java 12 引入了JEP 325 Switch 表达式。这个 JEP 放弃break value
了支持yield
从switch
表达式返回值的关键字。
PS 这是 Java 13 中的预览语言功能
传统的switch
语句,我们可以像这样返回一个值:
private static String getNumber(int number) {
String result = "";
switch (number) {
case 1:
case 2:
result = "one or two";
break;
case 3:
result = "three";
break;
case 4:
case 5:
case 6:
result = "four or five or six";
break;
default:
result = "unknown";
}
;
return result;
}
在 Java 12 中,我们可以使用break
从switch
.
private static String getNumberViaBreak(int number) {
String result = switch (number) {
case 1, 2:
break "one or two";
case 3:
break "three";
case 4, 5, 6:
break "four or five or six";
default:
break "unknown";
};
return result;
}
在 Java 13 中,上面的 Java 12value break
被删除,以支持yield
关键字返回值。
private static String getNumberViaYield(int number) {
return switch (number) {
case 1, 2:
yield "one or two";
case 3:
yield "three";
case 4, 5, 6:
yield "four or five or six";
default:
yield "unknown";
};
}
或者像这样
private static String getNumberViaYield2(int number) {
return switch (number) {
case 1, 2:
yield "one or two";
case 3:
yield "three";
case 4, 5, 6:
int i = 0;
i++;
yield "four or five or six : " + i;
default:
yield "unknown";
};
}
case L
Java 13 仍支持规则标签或箭头或。
private static String getNumberViaCaseL(int number) {
return switch (number) {
case 1, 2 -> "one or two";
case 3 -> "three";
case 4, 5, 6 -> "four or five or six";
default -> "unknown";
};
}
或者像这样,混合使用箭头语法和yield
.
private static String getNumberViaCaseL2(int number) {
return switch (number) {
case 1, 2 -> "one or two";
case 3 -> "three";
case 4, 5, 6 -> {
int i = 0;
i++;
yield "four or five or six :" + 1;
}
default -> "unknown";
};
}
PS 此开关表达式成为 Java 14 JEP 361 中的标准功能。
进一步阅读
5. JEP-355 文本块(预览)
这个 JEP 最后引入了一个多行字符串文字,一个文本块。
PS 此文本块是 Java 15 中的永久功能。
在 Java 13 之前
String html ="<html>\n" +
" <body>\n" +
" <p>Hello, World</p>\n" +
" </body>\n" +
"</html>\n";
String json ="{\n" +
" \"name\":\"mkyong\",\n" +
" \"age\":38\n" +
"}\n";
现在 Java 13
String html = """
<html>
<body>
<p>Hello, World</p>
</body>
</html>
""";
String json = """
{
"name":"mkyong",
"age":38
}
""";
注意
此文本块在Java 14 – JEP 368 中有第二个预览,添加了两个新的转义序列:
\<end-of-line>
抑制线路终止。\s
被翻译成一个空格。
要启用 Java 13 预览功能:
javac --enable-preview --release 13 Example.java
java --enable-preview Example
进一步阅读
下载源代码
$ git clone https://github.com/mkyong/core-java
$ cd java-13