Java 13 was released an hour ago and here’s everything new in this release. Of course, the big addition is text blocks, but there are also a few smaller ones like a refinement of

switch
expressions and a usability improvement for application class-data sharing. Here’s your overview with lots of links to more detailed articles.

Overview

If you want to play around with the code yourself, check out the Java X Demo on GitHub.

Language, APIs, JVM

Here’s what you get if you upgrade to Java 13.

Text Blocks

Putting strings that span several lines into code has been a pain in Java since its inception. Now, 20-something years later, we finally get easy-to-use multiline strings, called text blocks:

// ugh!
String jsonLiteral = ""
    + "{\n"
    + "\tgreeting: \"Hello\",\n"
    + "\taudience: \"World\",\n"
    + "\tpunctuation: \"!\"\n"
    + "}\n";
// yay! 🎉
String jsonBlock = """
    {
        greeting: "Hello",
        audience: "World",
        punctuation: "!"
    }
    """;

Text blocks start with three quotation marks and a newline (the opening delimiter; the newline is not part of the result) and end with three quotation marks either in the last line of content or on its own line (if the latter, the string ends with a newline). They are accepted in the exact same places where string literals

"like this one
" are. In fact, after the compiler processed them, they are absolutely indistinguishable from strings created by literals. That means
jsonLiteral.equals(jsonBlock)
is true and, thanks to String interning, even
jsonLiteral == jsonBlock
is. In Java 13, text blocks are a preview feature.

The compiler considers indentation that’s shared across all lines incidental and removes it. Other leading whitespace is considered essential and left in place. For

jsonBlock
that means that the lines with
{
and
}
have no indentation, but the property lines do. There’s lots more to indentation, which explain in my deep dive into text blocks.

Definite Guide To Text Blocks In Java 13Programmer’s Guide To Text Blocks (by Oracle) ⇝ JEP 355: Text Blocks

Returning Values From Switch Expressions

Switch expressions were introduced in Java 12 and 13 refines them. In 12 you would define return values with

break
:

boolean result = switch (Bool.random()) {
    case TRUE -> {
        System.out.println("Bool true");
        break true;
    }
    case FALSE -> {
        System.out.println("Bool false");
        break false;
    }
    case FILE_NOT_FOUND -> {
        throw new UncheckedIOException(
            "This is ridiculous!",
            new FileNotFoundException());
    }

In 13, you need to use

yield
:

boolean result = switch (Bool.random()) {
    case TRUE -> {
        System.out.println("Bool true");
        // `yield` instead of `break`
        yield true;
    }
    case FALSE -> {
        System.out.println("Bool false");
        yield false;
    }
    case FILE_NOT_FOUND -> {
        throw new UncheckedIOException(
            "This is ridiculous!",
            new FileNotFoundException());
    }

I slightly prefer the new variant. While

break
was easy to adopt for developers already familiar with Java, it was pretty odd. I mean, what is
break true
trying to tell me? The new (conditional) keyword
yield
is clearer, and in the future it may show up in other places where values are returned – in fact, Brian Goetz said it have been used for lambdas if they had thought of the necessity back then.

Due to this change,

switch
expressions are still in preview.

Definitive Guide To Switch Expressions In Java 13First Contact with Switch Expressions in Java 12 (video) ⇝ JEP 325: Switch Expressions (introduction in 12) ⇝ JEP 354: Switch Expressions (refinement in 13)

APIs

This is usually the place where I turn to new and updated APIs and tell you about all the small tidbits that will make your life easier. Except… there aren’t any in 13. Sad.

JDK 12 to 13 API Change Report

I got a big refactoring for you, though.

Socket And ServerSocket Reimplementation

Project Loom will introduce fibers (light-weight threads managed by the JVM) and a part of that is to have all code that blocks take the same paths (because those paths are then changed to no longer block threads). A critical part of the JDK where threads are blocked are the

java.net.Socket
und
java.net.ServerSocket
classes and their implementation was very old and didn’t line up with Loom’s approach. In preparation of future changes, this API was reimplemented. This should not be noticeable to us.

Project LoomJEP 353: Reimplement the Legacy Socket API

Creating Class-Data Archives For AppCDS

Application class-data sharing (AppCDS) was made freely available in Java 10 and improved in 12 and 13. It reduces launch times (by 10% to almost 50%) and response time outliers by moving much of the class-loading work out of the program run. Instead of loading class data from JARs when it’s needed, AppCDS prepares an immutable archive file and maps it into memory when the JVM launches. (Or "the JVMs" because the archive can be shared between multiple instances.)

On Java 10, using an archive used to be a three-step process:

  • creating a list of classes to archive
  • creating the archive
  • launching with the archive

Java 12 relaxed this a little by introducing a default archive of JDK classes that is shipped with the JVM and used automatically. But you still had to go through the steps above to create an archive that includes your application classes. This is where Java 13 comes into play.

The new option

-XX:ArchiveClassesAtExit
tells the JVM to run as usual, but on exit (if it didn’t crash), to write the class-data into the specified file. That can then be used on future program launches:

# run without CDS & create archive
java
    -XX:ArchiveClassesAtExit=dyn-cds.jsa
    -jar target/java-x.jar

# use created archive
java
    -XX:SharedArchiveFile=dyn-cds.jsa
    -jar target/java-x.jar

This approach uses so-called dynamic CDS archives and makes the feature much easier to use. If you care about launch times, give it a shot!

Improve Launch Times On Java 13 With Application Class-Data SharingJEP 310: Application Class-Data SharingJEP 341: Default CDS ArchivesJEP 350: Dynamic CDS Archives

ZGC Returns Unused Memory

Oracle’s Z Garbage Collector (ZGC) is a scalable low latency garbage collector designed to meet pause times that are independent of heap or live-set size (ranging from a few hundred MB to many TB) and stay below 10 ms. In Java 13, it can return unused memory to the operating system (much like G1 and Shenandoah). The command line argument

-XX:ZUncommitDelay=<seconds>
can be used to configure when that happens.

JEP 351: ZGC: Uncommit Unused Memory

Reflection

And that’s Java 13 for you:

  • text blocks (preview)
  • yield
    for
    switch
    expressions (preview)
  • dynamic AppCDS archives with
    -XX:ArchiveClassesAtExit
  • ZGCX returns unused memory

Now, go forth, download, and have fun!

The post Definitive Guide to Java 13 appeared first on blog@CodeFX.