What is new in Java 13 ?
Introduction
This is an alive post of what will become Java 13, and, as expected, this post will expand and change over time, until the development of Java 13 is freezed in 2019. I am planning to update this post when a new feature (JEP) is targeted for JDK 13, or when there is an important update on an already targeted JEP.
Last Update: 2020/01/31
Java 13 is released on 2019/09/17.
If something is a preview feature, it is fully specified and implemented, but provided in a release to gather feedback, thus it is not a permanent change yet. You need to use –enable-preview to use such features.
Changes
2020/01/31: Updated the post with GA (13.0.2).
2019/06/11: JEP 350, 351, 353, 354, 355 added. Using EA build 24 (2019/6/6).
2019/03/28: Schedule added.
2019/01/29: First time this post is published.
Java 13 Features
The list is taken from the OpenJDK JDK 13 project page.
JEP 350: Dynamic CDS Archives
This JEP simplifies using application class data sharing (AppCDS). Instead of providing a class list, an archive can be generated when the program exists by using -XX:ArchiveClassesAtExit=<filename>
. Then running the application with -XX:SharedArchiveFile=<filename>
enables sharing of class data on top of the system default archive in the JDK.
JEP 351: ZGC: Uncommit Unused Memory
ZGC is introduced in JDK 11, but until now it was not returning the unused heap memory to the operating system unlike the G1 Garbage Collector. This JEP addresses this issue and enables this capability by default.
JEP 353: Reimplement the Legacy Socket API
The implementations for java.net.Socket
and java.net.ServerSocket
is pretty old and this JEP introduces a modern implementation for them. The modern implementation is the default in Java 13, but the old implementations are not removed yet, and they can be used instead by setting the system property jdk.net.usePlainSocketImpl
.
No new implementation introduced for java.net.DatagramSocket
.
Running a class instantiating Socket and ServerSocket will show this debug output. Here is the default (new):
java -XX:+TraceClassLoading JEP353 | grep Socket
[0.033s][info ][class,load] java.net.Socket source: jrt:/java.base
[0.035s][info ][class,load] java.net.SocketOptions source: jrt:/java.base
[0.035s][info ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.039s][info ][class,load] java.net.SocketImpl$$Lambda$1/0x0000000800b50840 source: java.net.SocketImpl
[0.042s][info ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.042s][info ][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base
[0.043s][info ][class,load] sun.nio.ch.SocketDispatcher source: jrt:/java.base
[0.044s][info ][class,load] java.net.DelegatingSocketImpl source: jrt:/java.base
[0.044s][info ][class,load] java.net.SocksSocketImpl source: jrt:/java.base
[0.044s][info ][class,load] java.net.ServerSocket source: jrt:/java.base
[0.045s][info ][class,load] jdk.internal.access.JavaNetSocketAccess source: jrt:/java.base
[0.045s][info ][class,load] java.net.ServerSocket$1 source: jrt:/java.base
sun.nio.ch.NioSocketImpl
above is the new implementation.
Now lets set the system property and run again:
$ java -Djdk.net.usePlainSocketImpl -XX:+TraceClassLoading JEP353 | grep Socket
[0.037s][info ][class,load] java.net.Socket source: jrt:/java.base
[0.039s][info ][class,load] java.net.SocketOptions source: jrt:/java.base
[0.039s][info ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.043s][info ][class,load] java.net.SocketImpl$$Lambda$1/0x0000000800b50840 source: java.net.SocketImpl
[0.046s][info ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.047s][info ][class,load] java.net.AbstractPlainSocketImpl source: jrt:/java.base
[0.047s][info ][class,load] java.net.PlainSocketImpl source: jrt:/java.base
[0.047s][info ][class,load] java.net.AbstractPlainSocketImpl$1 source: jrt:/java.base
[0.047s][info ][class,load] sun.net.ext.ExtendedSocketOptions source: jrt:/java.base
[0.047s][info ][class,load] jdk.net.ExtendedSocketOptions source: jrt:/jdk.net
[0.047s][info ][class,load] java.net.SocketOption source: jrt:/java.base
[0.047s][info ][class,load] jdk.net.ExtendedSocketOptions$ExtSocketOption source: jrt:/jdk.net
[0.047s][info ][class,load] jdk.net.SocketFlow source: jrt:/jdk.net
[0.047s][info ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions source: jrt:/jdk.net
[0.047s][info ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions$1 source: jrt:/jdk.net
[0.048s][info ][class,load] jdk.net.LinuxSocketOptions source: jrt:/jdk.net
[0.048s][info ][class,load] jdk.net.LinuxSocketOptions$$Lambda$2/0x0000000800b51040 source: jdk.net.LinuxSocketOptions
[0.049s][info ][class,load] jdk.net.ExtendedSocketOptions$1 source: jrt:/jdk.net
[0.049s][info ][class,load] java.net.StandardSocketOptions source: jrt:/java.base
[0.049s][info ][class,load] java.net.StandardSocketOptions$StdSocketOption source: jrt:/java.base
[0.051s][info ][class,load] sun.net.ext.ExtendedSocketOptions$$Lambda$3/0x0000000800b51440 source: sun.net.ext.ExtendedSocketOptions
[0.057s][info ][class,load] java.net.DelegatingSocketImpl source: jrt:/java.base
[0.057s][info ][class,load] java.net.SocksSocketImpl source: jrt:/java.base
[0.058s][info ][class,load] java.net.ServerSocket source: jrt:/java.base
[0.058s][info ][class,load] jdk.internal.access.JavaNetSocketAccess source: jrt:/java.base
[0.058s][info ][class,load] java.net.ServerSocket$1 source: jrt:/java.base
It shows the old implementation java.net.PlainSocketImpl
is now used.
JEP 354: Switch Expressions (Preview)
Switch Expressions are introduced in JDK 12 as a preview feature. JEP 354 modifies this feature, it introduces the yield statement for returning a value from a block instead of using break. That means, a switch expression (returning a value) should use yield, and a switch statement (not returning a value) should use break.
For example:
System.out.println(switch (args[0]) {
case "1" -> 1;
case "2" -> 2;
default -> args[0].length();
});
or
System.out.println(switch (args[0]) {
case "1": yield 1;
case "2": yield 2;
default: {
int len = args[0].length();
yield len;
}
});
JEP 355: Text Blocks (Preview)
Raw String Literals feature are introduced in JDK 12 but dropped before the release. This JEP is similar in the sense that it introduces multi-line string literal, a text block.
Similar to Python, a multi-line text block can be defined (instead of using concatenation of single lines) like:
String lines = """
abc 1
def 2
""";
The first character of lines
above is a
and the last character is 2
but after 2
there is also an end of line marker. So the above definition is same as "abc 1\ndef 2\n"
. If the line termination at the end is not needed, it should be defined as:
String lines = """
abc 1
def 2""";
As it can be clear, the white spaces before abc 1
and def 2
is removed. The exact number of white spaces removed is the minimum number of white spaces of the text block start (the first “”") or the text block end (the last “”").
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.