loader image

What is new in Java 16?

The open-source Java 16 (Java SE 16 and JDK 16) is coming out tomorrow, on March 16th, 2021. and will be available to the general public. JDK 16 will be a short-term release, supported only for six months. JDK 17, due in September 2021, will be a long-term support (LTS) release that will receive several years of support. The current LTS release, JDK 11, was released in September 2018.

Java 16 release delivers 17 JDK enhancement proposals (JEP) that can be grouped into six categories:

394: Pattern matching for instanceof
395: Records

376: ZGC Concurrent Thread Processing
387: Elastic Metaspace

380: Unix-Domain Socket Channels
392: Packaging Tool

396: Strongly Encapsulate JDK Internals by default
390: Warning for Value-Based Classes

397: Sealed Classes (2nd preview)
338: Vector API (Incubator)
389: Foreign Linker API (Incubator)
393: Foreign Memory Access API (3rd Incubator)

347: Enable C++14 Language Features (in JDK source code)
357: Migrate from Mercurial to Git
369: Migrate to Github
386: Alpine Linux Port
388: Windows/AArch64 Port

Here is a look at language changes implemented in tomorrow’s release, since these are the changes that will most likely be visible to developers:

1.) Pattern matching for instanceof
Pattern matching allows common logic in a program, namely the conditional extraction of components from objects, to be expressed more concisely and safely. Here’s an example:

if (obj instanceof String) {

String s = (String) obj;

              // use s


There are three things going on in the code above:
a) We have to test if object is a String.
b) If it is, we have to declare a new String variable.
c) Then we have to cast our object into a new variable so we can treat is as a String.

Using Pattern Matching we can use a single line to achieve all of those three things:

If (obj instanceof String s)

  //use s

If there is an else statement, the variable would not be in scope in the conditional part:

    If (obj instanceof String s)

  // use s
    } else {
           // s is out of scope here!

2.) Records (previously introduced in JDK 14) is a special kind of Java class which has a concise syntax for defining immutable data-only classes. The Java compiler auto generates getter methods, toString(), hashcode() and equals() methods so you don’t have to write that boilerplate yourself.

For example, we can create a simple Person data class, with a name and an address:

While this accomplishes our goal, there are two problems with it:

a) There is a lot of boilerplate code.

b) We obscure the purpose of our class – to represent a person with a name and address.

While IDEs can automatically generate many of these classes, they fail to automatically update our classes when we add a new field. For example, if we add a new field, we have to update our equals method to incorporate this field.

A better approach would be to explicitly declare that our class is a data class.
To create a Person records, we simply use the record keyword:

While a public constructor is generated for us, we can still customize our constructor implementation. This customization is intended to be used for validation and should be kept as simple as possible.

For example, we can ensure that the name and address provided to our Person record are not null using the following constructor implementation:

We can also create new constructors with different arguments by supplying a different argument list:

That concludes all of language features of Java 16 release. If you are curious about the rest of the changes, provided below are brief explanations of each proposal with an external link to official OpenJDK documentation notes.

JEP 338: Vector API (Incubator)
Java Enhancement Proposal (JEP) will provide an initial iteration of an incubator module that can express vector calculations that are compiled at runtime. This module will be clear and concise, platform agnostic, have reliable runtime compilation and performance on x64 and AArch64 architectures, and offer graceful degradation when a vector computation cannot be fully expressed, the OpenJDK team explained. 

JEP 347: Enable C++14 Language Features
The goal of this addition is to support C++14 language features and give specific guidance on which features can be used in HotSpot code.
It basically means the code will be compiled with std=c++14 like options in all platforms (Windows, Linux, macOS, AIX).

JEP 357: Migrate from Mercurial to Git
This JEP relates to the goal of migrating the OpenJDK Community’s source code repositories from Mercurial to Git, and specifically to GitHub.

JEP 369: Migrate to GitHub
Similar to JEP 357, this relates to the goal of hosting the OpenJDK Community’s Git repositories on GitHub. All single-repository OpenJDK projects, including JDK feature releases and JDK update releases for versions 11 and later, will be migrated. You can follow the OpenJDK profile here:  https://github.com/openjdk 

JEP 376: ZGC: Concurrent Thread-Stack Processing
This will remove thread-stack processing from ZGC safepoints; make stack processing lazy, cooperative, concurrent, and incremental; remove per-thread root processing from ZGC safepoints and provide a mechanism for HotSpot subsystems to lazily process stacks, according to OpenJDK. This is done to eliminate effectively all pause and scalability issues.

JEP 380: Unix-Domain Socket Channels
Unix-domain sockets are used for inter-process communication, and are similar to TCP/IP sockets, except they are addressed by filesystem path names instead of IP addresses and port numbers. It is intended for Java to support all Unix-domain socket features common across major Unix platforms and Windows. 

JEP 386: Alpine Linux Port
The goal of this JEP is to port the JDK to Alpine Linux and other Linux distributions that use musl as their primary C library.

JEP 387: Elastic Metaspace
According to OpenJDK, Metaspace has been notorious for using a lot of off-heap memory, so the goal of this feature is to return unused HotSpot class-metadata to the operating system, reduce metaspace footprint, and simplify metaspace code to reduce maintenance costs. 

JEP 388: Windows/AArch64 Port
The JDK will complete its port to Windows/AArch64. 

JEP 389: Foreign Linker API (Incubator)
Java will introduce an API that offers “statically-typed, pure-Java access to native code.” In combination with the Foreign-Memory API, this will simplify the process of binding to a native library, which is an error-prone process. 

JEP 390: Warnings for Value-Based Classes
This feature will designate primitive wrapper classes as value-based. It will also deprecate their constructors for removal, which will launch new deprecation warnings. 

JEP 392: Packaging Tool
The new JPackage tool can be used to package Java applications. 

JEP 393: Foreign-Memory Access API (Third Incubator)
This API enables applications to safely access foreign memory that is outside the Java heap. It was created because many Java applications access foreign memory, but the Java API doesn’t have an efficient or safe way of accessing foreign memory. 

JEP 394: Pattern Matching for instanceof
The goal of this feature is to enhance the pattern matching capability on the instanceof operator. According to the OpenJDK team, pattern matching allows common logic to be expressed concisely and safely. 

JEP 395: Records
Records are classes that can act as “transparent carriers for immutable data,” the OpenJDK team explained. They can be helpful with modeling data aggregates. 

JEP 396: Strongly Encapsulate JDK Internals by Default
According to the team, this change will encapsulate internal elements by default, except for critical internal APIs like sun.misc.Unsafe. The motivation behind this strong encapsulation is that developers of libraries, frameworks, and tools often use internal elements in ways that compromise security and maintainability. Strong encapsulation ensures that code outside of a module can only access public and protected elements of a package, and that protected elements can only be accessed from subclasses of their defining classes. 

JEP 397: Sealed Classes (Second Preview)
This is the second preview of Sealed Classes introduced with JEP 360 in JDK 15 with a few improvements.
Sealed classes restrict which other classes extend or implement them. They will allow the author of a class to control what code can be used to implement it, provide a more declarative way of restricting access, and support future directions in pattern matching.