Java 13已于2019年9月17日正式发布,请在此处下载Java 13。
Java 13中的一些新功能
- JEP 350:动态CDS档案
- JEP-351:ZGC:取消提交未使用的内存
- JEP-353:重新实现旧版套接字API
- JEP-354:开关表达式(预览)(开发人员功能)
- JEP-355:文本块(预览)(开发人员功能)
1. JEP 350动态CDS档案
该JEP 通过简化创建CDS档案的过程,增强了Java 10中引入的JEP 310应用程序类数据共享。
如果程序存在,则将创建CDS存档 -XX:ArchiveClassesAtExit
$ java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
使用上面的CDS档案运行程序。
$ bin/java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello
类数据共享(CDS)背后的思想是通过一次创建类数据存档然后再使用它来提高启动性能的功能,因此JVM无需再次创建它。
请阅读以下文章,以了解有关CDS的更多信息:
2. JEP 351 ZGC:取消提交未使用的内存
该JEP 333位:Z垃圾收集器是用Java 11推出时,清理堆回忆,当提供一个短暂的停顿时间。但是,即使长时间未使用该内存,它也不会将未使用的堆内存返回给操作系统。
该JEP通过将未使用的堆内存返回给操作系统来增强ZGC。
3. JEP-353重新实现旧版套接字API
的底层实现java.net.Socket
和java.net.ServerSocket
非常古老,可以追溯到JDK 1.0,它是传统的Java和C代码的混合,是很难维护和调试。该JEP为Socket API引入了新的基础实现,它是Java 13中的默认实现。
在Java 13之前,它将PlainSocketImpl
用作SocketImpl
ServerSocket.java
public class ServerSocket implements java.io.Closeable {
/**
* The implementation of this Socket.
*/
private SocketImpl impl;
}
在Java 13中,它引入了一个新NioSocketImpl
类来代替PlainSocketImpl
。但是,如果出现问题,我们仍然可以PlainSocketImpl
通过设置jdk.net.usePlainSocketImpl
系统属性来切换回旧的实现
查看一个简单的Socket示例。
JEP353.java
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();
}
}
}
跟踪上述Socket类的类加载。在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
4. JEP-354开关表达式(预览)
该JEP增强了以前的Java 12 JEP 325 Switch表达式,因此可以用作语句(不返回内容)或表达式(返回内容)。引入了新的关键字“ yield”以从开关返回值。
PS这是Java 13中的预览语言功能
在Java 12传统switch
语句之前,我们可以返回如下值:
private static String getText(int number) {
String result = "";
switch (number) {
case 1, 2:
result = "one or two";
break;
case 3:
result = "three";
break;
case 4, 5, 6:
result = "four or five or six";
break;
default:
result = "unknown";
break;
};
return result;
}
在Java 12中,我们可以用来break
从中返回值switch
。
private static String getText(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 12 value break
不再被编译,我们应该使用它yield
来返回一个值。
private static String getText(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";
};
}
switch
Java 13仍支持Java 12 规则标签或箭头语法。
private static String getText(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";
};
}
注意
有关完整示例,请阅读此Java 13开关表达式
5. JEP-355文本块(预览)
该JEP最终引入了多行字符串文字,文本块。
PS这是Java 13中的预览语言功能
在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 13预览功能:
javac --enable-preview --release 13 Example.java
java --enable-preview Example