Main Tutorials

What is new in Java 13

Java 13 logo

Java 13 reached General Availability on 17 September 2019, download Java 13 here or this openJDK archived.

Java 13 features.

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

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

ServerSocket.java

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.

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();
        }

    }
}

In Java 13, the default implementation is NioSocketImpl

Terminal

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.

Terminal

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

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
12 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Madan
4 years ago

Thanks bro it’s really helpful

Francoo
4 years ago

Nice

Ravisankar.P.R
4 years ago

Nice to read..thanks

Prashant Tiwari
4 years ago

Great! Thanks !

Fede
4 years ago

Great! Thanks !

ZAIT
3 years ago

Great! Thanks !
عظيم! شكر !

Shradha
3 years ago

What is future of Java? where it will be stand in 2025?

jacob
4 years ago

Its good that java is still evolving, but these features (plus more) has been in other JVM languages (groovy, Kotlin) for ages.

Karthicks
4 years ago

I find the article to be useful.

Rahul Kumar
4 years ago

thanks sir.

Dean
4 years ago

Thanks for the summary. There’s really nothing to get excited about, though.

guilherme
4 years ago

thanks for compiling it, great article