Java 14 is going to be released on March 17, 2020. Besides ~2,400 bug fixes and small enhancements, the new version of Java contains 16 major enhancements, also called JEPs (Java Enhancement Proposals).
Let’s take a closer look at the major updates in Java 14: new switch expressions, better NullPointerException
s, improvements in garbage collection, JFR event streaming, and more.
Image source: Author
Switch Expressions
This update to the Java language was already available in Java 12 and 13 but only as a preview language feature, which means it was not enabled by default. Finally, the new switch expressions are released in Java 14. Making a long story short, Java 14 introduces a new simplified form of a switch block with case L -> ...
labels. The new switch expressions may help to simplify code in some cases. Here are a couple of examples.
Let’s assume that we have an enum that describes weekdays. We can write the following code using the new switch expressions:
Here we just used a single expression for each case
. Note that the switch
block doesn’t use any break
statement, which makes it much shorter. The next example shows how the new switch expressions can return a value:
It’s also possible to write multi-line blocks and return a value with a new keyword yield
:
There are several important things that you need to keep in mind when you use the new switch expressions. For example, the cases of new switch expressions have to be exhaustive. It means that, for all possible values, there has to be a matching switch label. Or, since yield
is now a keyword, a class with a name yield
now becomes illegal in Java 14.
If you’d like to learn more about the new switch expressions, you’re welcome to read JEP 361. The authors provided quite a lot of useful info about the new switch expressions.
Helpful NullPointerExceptions
The JVM throws a NullPointerException
(NPE) when code tries to dereference a null reference. All Java developers have seen them before. For example, the following code may result in an NPE:
foo.bar = 10;
The NPE is going to look like the following:
The exception message contains a filename and a line where the null dereference happened. For the foo.bar = 10;
statement, it’s not too difficult to figure out that the NPE was thrown because the foo
variable was null. Unfortunately, sometimes it’s not clear what exactly causes an NPE. For example, if either a
, b
or c
is null, then an NPE is going to be thrown:
a.b.c.d = 42;
However, no matter which field was null, the NPE is going to look the same. It doesn’t give any clue which field was actually null.
Here is another example. If one of the nested arrays is null, it results in an NPE:
a[i][j][k] = 99;
Again, no matter which array was null, the NPE is going to look the same.
Java 14 addresses this problem and makes NPEs more friendly. Now the JVM can figure out which variable was null, and then it lets the user know about it in the exception message. For example, a null dereference in the line foo.bar = 10;
is going to result in the following NPE:
A null dereference in the line a.b.c.d = 41;
is going to result in the following NPE if a.b
was null:
The new info in NullPointerException
s may be very helpful in analyzing its root cause and can make the developer’s life a bit easier. By the way, the improvement has been available in SAP’s JVM since 2006. Unfortunately, it took 14 years to finally bring it into OpenJDK.
If you’re interested in the details, the authors of the JEP 358 provided a lot of info about the new feature.
Packaging Tool (Incubator)
Currently, a Java application is usually distributed as a simple JAR file. However, it’s not very convenient, especially for a user of the application. It would be much better if the Java application were an installable package like MSI on Windows or DMG on Mac. This would allow Java applications to be distributed, installed, and uninstalled in a way that is familiar to users.
JEP 343 introduces the jpackage
tool, which packages a Java application into a platform-specific package that includes all of the necessary dependencies. Here’s a list of supported package formats:
- DEB and RPM on Linux
- PKG and DMG on macOS
- MSI and EXE on Windows
Here is an example of how the new tool can be used:
It takes the lib/main.jar
file and produces a package in the format most appropriate for the system on which it is run. The entry point is the myapp.Main
class.
The JEP’s authors provided quite a lot of useful information about the new tool.
Although the jpackage
tool is available in JDK 14, it’s delivered as an incubator module, which means that the functionality is not guaranteed to be stable and may be revised in a future release.
Better Garbage Collection
Java 14 contains multiple enhancements in garbage collection.
JEP 345 improves the G1 garbage collector by implementing NUMA-aware memory allocation. By the way, NUMA stands for Non-Uniform Memory Access. This feature has been implemented in the parallel garbage collector for a long time. Now it can be enabled in the G1 as well by running Java with a new +XX:+UseNUMA
command-line option. This should improve G1 performance on large machines.
JEP 363 removes the Concurrent Mark Sweep (CMS) garbage collector which was deprecated a couple of years ago. Goodbye CMS!
JEP 364 and JEP 365 make the Z garbage collector (ZGC) available on macOS and Windows. ZGC is a concurrent garbage collector that was added to the JVM a couple of years ago. ZGC tries to reduce pause times for garbage collections and can handle heaps of size ranging from a few hundred megabytes to multi-terabytes. Previously, the collector could run only on Linux.
-XX:+UseParallelGC -XX:-UseParallelOldGC
command-line options. The authors believe that the combination is uncommon but requires a significant amount of maintenance effort. In fact, the option -XX:UseParallelOldGC
is now deprecated. A warring is going to be displayed if the deprecated modes are used.
JFR Event Streaming
JDK Flight Recorder (JFR) is an event recorder that is built into the JVM. It captures diagnostic and profiling data about the JVM itself, and the application running in the JVM. JFR used to be a proprietary tool, but it was open-sourced in 2018 Java released as part of OpenJDK 11.
To consume the data provided by JFR, a user has to start a recording, stop it, dump the contents to disk, and then parse the recording file. This works quite well for application profiling but not for monitoring purposes.
In Java 14, the JFR allows users to subscribe to events asynchronously. Users can now register a handler that’s going to be invoked in response to the arrival of an event. The RecordingStream
class provides a uniform way to filter and consume events. Here is an example provided by the JEP’s authors:
More info can be found in JEP 349.
Language preview features
Java 14 contains several updates to the Java language with are not yet available by default.
First, JEP 305 extends the instanceof
operator with a binding variable. Here is an example:
If obj
is an instance of String
, then it is cast to String
and assigned to the binding variable s
.
Second, JEP 359 introduces records to the Java language. A record has a name and a state description. The state description declares the components of the record. A record may also have a body. Here is a short example:
record Point(int x, int y) {}
Third, after collecting feedback for Java 13, JEP 368 adds a couple of new escape sequences for the text blocks that were previously introduced in Java 13 as a language preview feature.
Unfortunately, these three updates are still only available as preview language features that are not enabled by default. To enable the new syntax, you’ll have to run the Java compiler with --enable-preview --release 14
options and then launch java
with --enable-preview
option:
The Rest
What else has changed in Java 14?
JEP 370 introduces an API to allow Java applications to safely and efficiently access foreign memory outside of the Java heap. Sounds scary. The new API should become an alternative to the java.nio.ByteBuffer
and sun.misc.Unsafe
classes. This feature is provided as an incubating module.
JEP 352 adds new file mapping modes so that the FileChannel
API can be used to create MappedByteBuffer
instances that refer to non-volatile memory (NVM).
The Pack200 tool was deprecated in Java 11. Now JEP 367 removed the tool and its API.
In case you know about Solaris and SPARC, JEP 362 drops support for the Solaris/SPARC, Solaris/x64, and Linux/SPARC platforms. In the future, the ports on these platforms most likely are going to be removed from OpenJDK.
Conclusion
Compared to the five JEPs in Java 13, the new Java 14 delivers many more major enhancements. The updates touch various areas. Most likely, the most interesting updates for Java developers are going to be the new switch expressions and the enhanced NullPointerException
s. Don’t forget to try out the new language preview features and provide your feedback to the JDK developers. Enjoy the new Java 14!