Java developers, nowadays, are spoiled with a new release every 6 months, Java 13 being the second release this year. In this blog post, I’m assuming that you’re somewhat familiar with updates that have been shipped with previous Java versions. If not, let me know and maybe I’ll cover those as well in a separate post.

 

So, what’s happening in Java 13? 

Looking back to the features added in previous Java versions, it looks like Java is “borrowing” features from pure functional programming languages like Javascript and that’s great! It all started with adding functional capabilities ( functional interfaces, lambda expressions, streams API ). Then, using var keyword for Local Variables Type Inference and now adding yield statement and Text Blocks. The entire Java 13 release has been focused around 5 features ( 2 preview features and 3 platform updates ) which I’ve detailed below. Of course, there are a lot of API improvements and deprecations but since an average developer will encounter them every now and then I’ve decided not to cover them into this blog post. If you are more interested in all the changes you can find all the details that you need overhere.

 

Preview Features

First time when I saw this term, I was actually intrigued so I looked it up on the OpenJDK website and this is what I found:

A preview language or VM feature is a new feature of the Java SE Platform that is fully specified, fully implemented, and yet impermanent. It is available in a JDK feature release to provoke developer feedback based on real world use; this may lead to it becoming permanent in a future Java SE Platform

 –  JEP 12

In other words, a preview feature is not meant to be used in production and its primary goal is to actually get feedback from the developers and improve it before it makes its way to a permanent feature.

 

Switch Expressions

Switch Expressions have been actually introduced in Java 12 but it hasn’t been yet finalized so even in Java 13 it is declared as a preview feature. Just a quick reminder on how a Switch Expression looks like:

Java 12 Switch Expressions

Pretty straightforward, huh? “Switch” can now be used as an expression and not just as a statement. You can assign the result of this expression to a variable, play out with the cases ( like chaining them ) and most importantly, every switch case is represented by a “lambda” expression ( it’s not actually a functional interface but it looks like one ).

Let’s now have a look over what has been changed in Java 13:

Java 13 Switch Expressions

It seems that the “break” statement was too confusing so starting off Java 13 it has been replaced with the “yield” statement. Just as a curiosity, the same keyword is being used in JavaScript generatorfunctions even though they are meant to serve a different purpose.

 

Text blocks

This feature is going to be loved by so many developers who deal with building complex Strings in their code. I think almost every java dev has encountered code similar to the one below at least a couple of times in his career:

Java 12 Inline JSON

There are a couple of issues which clog the readability of this JSON. All quotes need to be escaped which makes it a very labor-intensive job, especially when you need to copy this piece of text from a different source. Next, we have end-line characters which reduce even more the visibility of the end result. There is one thing that we can do to improve the readability from this perspective:

Java 12 Multi-line JSON

This actually improves a lot the readability from the new line perspective but it’s still very hard to ignore all those escaped characters and extra quotes. Java 13 comes to our rescue with text blocks:

Java 13 Text Blocks

This feature has actually improved a lot the readability of our JSON. We can clearly distinguish the new lines, there is no need to escape the quotes and the best part of it, we can just copy any text to our file and there will be no need for escaping! All that you need to do is to prefix your text with 3 quotes ( “”” ) and then end with using the same structure.

 

Something Extra

Java 13 text blocks are the first step to creating template literals more easily by using a new API that has been introduced to the String class: .formatted(Object… args) 

We can actually use our string literal as a template and dynamically replace the values, everything done using text blocks and the new API on the String class.

 

Platform Features

The API changes usually are the most popular since that is something you can clearly work with. Platform updates, otherwise, are not something that you can experience first hand but it is good to keep an eye on them because it will help you understand why something works in a specific way.

 

Dynamic CDS Archive

CDS or Class Data Sharing is a feature added in Java 5 which can be used mainly for decreasing start-up time and memory footprint of applications while running them in different JVM instances. How does it work? By passing certain arguments, the JVM will create an “archive” of a set of classes which then can be loaded to another JVM. When we load this archive to another JVM instance we’re actually bypassing a lot of steps like loading the classes, parsing and verifying the bytecode so the start-up time will be increased drastically. At first, this feature was only capable to archive classes loaded by the System Classloader but starting with Java 10, the functionality has been extended in such a manner that it can also archive classes loaded by the Application Classloader. 

Java 10: CDS – creating the archive

There are a couple of things going on in here:

  • The first 2 arguments are used for telling the JVM that we want to use the Application CDS feature and dump the result in an archive;
  • hello.lst contains a list of all the application classes that we want to include in the archive;
  • hello.jsa the name of the resulting archive;
  • the rest is well known;

Now when it comes to loading that specific archive:

Java 10: CDS – loading the archive

It is pretty straightforward:

  • firstly, we specify that we want to use the AppCDS feature;
  • then we pass the name of the archive that we want to load;
  • the rest is well known;

As you’ve probably guessed the trickiest part of this flow is to create the hello.lst file which contains the list of the classes that you want to be included in an archive. For a single class application it’s relatively easy but for enterprise applications that can be quite cumbersome.

The solution comes from Java 13: 

Java 13: CDS – creating the archive

Now, instead of passing all those long arguments we can simply state that we want to create an archive with all the application classes loaded when exiting the application: simply and efficient. No need for manually creating the .lst file, no need for passing complex JVM arguments.

To simply load the archive at startup we can use the following command:

Java 13: CDS – using the archive

So, when should you use this feature? Typically, we don’t really care how fast our application starts up ( as long it is in an acceptable range ) but there are a couple of use cases where every millisecond count. One of them is serverless applications which has become extremely popular in the last couple of years. 

 

ZGC: Uncommit unused memory

ZGC ( Z Garbage Collector ) has been introduced in Java 11 as an experimental garbage collector. Its main goal is to perform all the gc tasks in a low latency manner, without stopping the execution of the application threads for more than 10 ms.

In the previous versions, this Garbage Collector was not able to uncommit the unused memory back to the operating system. In other words, if some of the memory was still unused by the JVM after a long time, the Garbage Collector should have freed up that memory and return it to the Operating System.

 

Reimplement the legacy Socket API

The already existing java.net.Socket and java.net.SocketServer API’s have been introduced in the JDK since version 1 so you can probably guess why an update was required. The old implementation was using a mix of legacy Java and C code which was painful to debug, it was running into some concurrency issues, and the underlying implementation was using the thread stack as the I/O buffer which required to often increase the default thread stack size.

The new implementation is more modern and it has also been designed as anticipation to fibers ( user-mode threads ) currently being explored in Project Loom.