What is new in Java 13
Java 13 reached General Availability on 17 September 2019, download Java 13 here or this openJDK archived.
Java 13 features.
- 1. JEP 350 Dynamic CDS Archives
- 2. JEP 351 ZGC: Uncommit Unused Memory
- 3. JEP-353 Reimplement the Legacy Socket API
- 4. JEP-354 Switch Expressions (Preview)
- 5. JEP-355 Text Blocks (Preview)
Java 13 developer features.
Switch expression (preview), text blocks or multi-lines (preview)
1. JEP 350 Dynamic CDS Archives
Java 10 introduced JEP 310 Application Class-Data Sharing. This JEP simplifying the process of creating CDS archives.
This command creates a CDS archive file of a .jar
.
$ java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
This command runs a .jar
with an existing CDS archive.
$ bin/java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello
The Class Data Sharing (CDS) improves startup performance by creating a class-data archive once and reusing it so that the JVM needs not to recreate it again.
Further Reading
- JEP 350 Dynamic CDS Archives
- cl4cds
- Improve Launch Times On Java 13 With Application Class-Data Sharing
2. JEP 351 ZGC: Uncommit Unused Memory
Java 11 introduced the JEP 333: Z Garbage Collector (Experimental); it provides a short pause times when cleaning up heap memories. However, it didn’t return unused heap memory to the operating system, even when it was unused for a long time.
This JEP enhanced the ZGC by returning unused heap memory to the operating system.
Further Reading
3. JEP-353 Reimplement the Legacy Socket API
The underlying implementations of java.net.Socket
and java.net.ServerSocket
are ancient, dating back to JDK 1.0, a mix of legacy Java and C code that is hard to maintain and debug. This JEP introduces new underlying implementations for the Socket APIs, which is the default implementation in Java 13.
Before Java 13, it uses the PlainSocketImpl
for the SocketImpl
public class ServerSocket implements java.io.Closeable {
/**
* The implementation of this Socket.
*/
private SocketImpl impl;
}
Java 13 introduced a new NioSocketImpl
class as a drop-in replacement for PlainSocketImpl
. However, if something goes wrong, we can still switch back to the old implementation PlainSocketImpl
by setting jdk.net.usePlainSocketImpl
system property.
Review a simple Socket example.
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();
}
}
}
In Java 13, the default implementation is 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
We can switch back to PlainSocketImpl
by setting the Djdk.net.usePlainSocketImpl
system property.
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
P.S Java 15 JEP 373: Reimplement the Legacy DatagramSocket API, replace the underlying implementations of the java.net.DatagramSocket
and java.net.MulticastSocket
.
Further Reading
4. JEP-354 Switch Expressions (Preview)
Java 12 introduced JEP 325 Switch expressions. This JEP dropped break value
in favor of yield
keyword to return a value from switch
expressions.
P.S This is a preview language feature in Java 13
The traditional switch
statement, we can return a value like this:
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;
}
In Java 12, we can use break
to return a value from a 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;
}
In Java 13, the above Java 12 value break
is dropped in favor of yield
keyword to return a value.
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";
};
}
or like this
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";
};
}
The rule labels or arrow or case L
is still supported in 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";
};
}
Or like this, mixed the use of arrow syntax and 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";
};
}
P.S This switch expression becomes a standard feature in Java 14 JEP 361.
Further Reading
5. JEP-355 Text Blocks (Preview)
This JEP introduces a multi-line string literal, a text block, finally.
P.S This text blocks is a permanent feature in Java 15.
Before 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";
Now Java 13
String html = """
<html>
<body>
<p>Hello, World</p>
</body>
</html>
""";
String json = """
{
"name":"mkyong",
"age":38
}
""";
Note
This text block has a second preview in Java 14 – JEP 368, added two more new escape sequences:
\<end-of-line>
suppresses the line termination.\s
is translated into a single space.
To enable the Java 13 preview features:
javac --enable-preview --release 13 Example.java
java --enable-preview Example
Further Reading
Download Source Code
$ git clone https://github.com/mkyong/core-java
$ cd java-13
Thanks bro it’s really helpful
Nice
Nice to read..thanks
Great! Thanks !
Great! Thanks !
Great! Thanks !
عظيم! شكر !
What is future of Java? where it will be stand in 2025?
Its good that java is still evolving, but these features (plus more) has been in other JVM languages (groovy, Kotlin) for ages.
I find the article to be useful.
thanks sir.
Thanks for the summary. There’s really nothing to get excited about, though.
thanks for compiling it, great article