What is new in Java 13

Java logo

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

Java 13 features.

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.

Please read the articles below to understand more about CDS:

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.

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

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";
      };
  }

Java 14
This switch expression becomes a standard feature in Java 14 – JEP 361

Note
For full example, please read this Java 13 Switch Expressions

JEP-355 Text Blocks (Preview)

This JEP introduces a multi-line string literal, a text block, finally.

P.S This is a preview language feature in Java 13

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
                }
                """;

Further Reading
More multi-line string, text blocks examples

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

Download Source Code

$ git clone https://github.com/mkyong/core-java

$ cd java-13

References

author image

mkyong

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. Read all published posts by

Comments

avatar
newest oldest most voted
Madan
Guest
Madan

Thanks bro it’s really helpful

Fede
Guest
Fede

Great! Thanks !

Francoo
Guest
Francoo

Nice

guilherme
Guest
guilherme

thanks for compiling it, great article

Prashant Tiwari
Guest
Prashant Tiwari

Great! Thanks !

Ravisankar.P.R
Guest
Ravisankar.P.R

Nice to read..thanks

Dean
Guest
Dean

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

Rahul Kumar
Guest
Rahul Kumar

thanks sir.

Karthicks
Guest
Karthicks

I find the article to be useful.

jacob
Guest
jacob

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

Shradha
Guest
Shradha

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

ZAIT
Guest
ZAIT

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