What's New In Java 16?

Here in this article, we will address new features in the latest update of Java i.e Java 16. 

Java16 delivers 17(JEP) which stands for JDK Enhancement proposals and all the changes are not grouped into 6 categories.

  • Two changes for Java Language
  • Two improvements in memory management for JVM
  • One new API
  • One new Tool.

JDK16 also helps developers to prepare later versions of the platform i.e making it easier for them to move with Java. 

First, let's take a look at the language features. Since these are more used by the developers, changes to it make it possible to write java code more concisely.

Language Features

Pattern Matching for instanceOf

We can use this feature without any flag. Enhance the Java programming language with pattern matching of instanceOf operator.

According to Oracle docs, JDK 16, pattern matching allows common logic in a program, namely the condition extraction of components from objects, to be exposed more concisely and safely.

For example, (before this feature)

if (obj instanceOf String) {
    String str = (String) obj;
    //use str
}

We have an object that will hold different types & want to do something if it happens to be of a particular type. In this snippet above, we have 3 things going here,

  • Checks obj is a String.
  • Declaration of new variable str.
  • Casting of obj to string into variable str.

But with pattern matching, we can reduce the code into a single line that does 3 things. So in this example, the variable str is only created if the object is a string and it is automatically cast into a variable.

After this feature,

if (obj instanceof String str) {
    //use str
} else {
    //str is out of scope here.
}

If there is an else statement then variable str would be out of scope in the conditional path. Even with the more advanced conditionals, the scope of the variable behaves as you expect.

For example,

if (obj instanceof String str && str.length() > 5) {
    str.contains("______");
}

Here, the second part of the code statement is only executed when the first is true. However, if we are using this statement with “OR”.

For example,

if (obj instanceof String str || str.length() > 5) {
    str.contains("______");
}

The second part of the statement is only evaluated if the first part is false then variable ‘str’ will not be in scope after the OR and try to use the second part which would lead to an error.

error java: cannot find symbol.
symbol: variable str
location: classmain
 
Records

The second change to the language in JDK16 is the addition of record type.

According to Oracle docs, records provide a compact syntax for declaring classes that are transparent holders for shallowly immutable data.

In simple words, records save developers the need to write some of the boilerplate that one has to create while writing a class that simply aggregates immutable data.

For example,

A Point class that represents coordinates we only want to pass around an immutable(final) pair of integers to a constructor to set the values.

class Point {
    final int x_coordinate;
    final int y_coordinate;
    //constructor
    public Point(int x_coordinate, int y_coordinate) {
        super();
        this.x_coordinate = x_coordinate;
        this.y_coordinate = y_coordinate;
    }
    //getters
    public int getX_coordinate() {
        return x_coordinate;
    }
    public int getY_coordinate() {
        return y_coordinate;
    }
    @Override
    public String toString() {
        return "Point [x_coordinate=" + x_coordinate + ", y_coordinate=" + y_coordinate + "]";
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x_coordinate;
        result = prime * result + y_coordinate;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) returntrue;
        if (obj == null || getClass() != obj.getClass()) returnfalse;
        Point point = (Point) obj;
        if (x_coordinate != point.x_coordinate) returnfalse;
        if (y_coordinate != point.y_coordinate) returnfalse;
        return true;
    }
}

All of this code could be generated by iDE, now what if Java handles this for us? Instead of saying class, we say Record (record Point (int x_coordinate, int y_coordinate)).

Here, the compiler will make sure that records get all of those required methods without having us include them in a code.

According to Oracle docs, any of the members that are automatically derived from the state description can also be declared explicitly.

Now changes to the language make it easier to write in your code changes to JVM. 

JVM Features

JDK16 brings us two new changes to the JVM.

ZGC(Concurrent Thread-Stack Processing)

According to Oracle docs, 

  • Move ZGC thread-stack processing from safepoints to a concurrent phase.
  • Allow sub millisecond pause inside GC safepoints, even on large heaps.
  • These changes remove the final source of latency in the ZGC garbage collector.

In normal words, the first change is concurrent thread-stack processing; those who are using the set coverage collection which is not the default will see an improvement in how the average collection is processed.

With JDK16 we move the last important part of work that was being done in the same points to the concurrent phase, this removes the last roadblock for ZGC making advantage of partial processing.

Elastic MetaSpace(JEP 387)

The second JVM Enhancement was from the area of memory management for metaspace.

According to Oracle docs, it returns unused Hotspot class-metadata memory to the operating system more promptly, reducing the metaspace footprint.

Applications with heavy class loading and unloading activity can accrue a lot of unused space. The new scheme allocates metaspace memory in smaller chunks, reduces class-loader overhead and fragmentation as well as improves elasticity by returning unused metaspace memory to the operating system.

In normal words, before this change when the memory of the metaspace was no longer needed it was returned to the JVM but JVM in return didn’t return it to the operating system properly. With this change now JVM allocates memory in smaller chunks reducing the classloader overhead and fragmentation which makes it easier to return the unused space to the operating system.

With this JDK will now be able to return memory more quickly so the applications will run with a smaller total memory footprint.

Library and Tools

Now changes to the library can bring you functionality or make it easier to a task when a new API is introduced. 

In JDK16, a new API for inter-process communication & a new tool to make it easier to deliver.

Unix Domain Socket Channels(JEP 380)

Unix Domain Socket is similar to TCP socket but meant to be used for inter-process communication rather than communication with servers. They can be addressed by file system path rather than internet protocol ports and numbers. They are more secure and efficient than using a TCP loopback connection.

Unix Domain Socket Channels are used by all major domains and by windows thus add features to Unix and Windows.

According to Oracle docs, we have to add Unix-domain(AF_UNIX) socket support to the socket channel and server-socket channel APIs in the java.nio.channels package and extend the inherit channel mechanism to support Unix-domain socket channels and server socket channels.

Unix-domain sockets are used for inter-process communication(IPC) on the same host. They are similar to TCP/IP sockets in most respects, except that they are addressed by filesystem pathnames rather than Internet Protocol(IP) address and port numbers. 

For local, inter-process communication, Unix-domain sockets are both more secure and more efficient than TCP/IP loopback connections. 

Packaging Tool(JEP 392)

In normal words, the packaging tool is explained as, using the new packaging tool we can wrap the application plus a runtime and it can be either a full runtime or smaller version.

According to Oracle docs, it is a tool for packaging self-contained Java applications, supports native packing formats to give end-users a natural installation experience. These formats include MSI and EXE on Windows, pkg, and dmg on macOS, and deb and rpm on Linux and allows launch-time parameters to be specified at packaging time. It can be invoked directly, from the command line, or programmatically, via the ToolProvider API.

Other Changes

Warning for Value-Based Classes

Some of the classes that currently exist in Java are likely to be converted to primitive classes; those classes are called value-based classes.

 Wrapper classes such as java.lang.Integer or java.lang.Double satisfy most of the requirements to be designated value-based classes except they continue to expose public constructors.

Additionally JDK16, now emits warnings if you try to synchronize on instanceOf any value-based class, will get a one-time warning and when possible you will get compile-time warnings.

Example:

Double d = 50.0;
synchronized(d) {...}// javac warning and hotspot warning

Object obj =d;
synchronized(obj) {...}// Hotspot warning

According to Oracle docs, designate for primitive wrapper classes (java.lang.Integer, java.lang.Double, etc) as value-based (similar to java.util.Optional and java.time.LocalDateTime) and add forRemoval to their constructors, which are deprecated since JDK 9, promoting new warnings.

 

Example - instead of a new Integer(4) use Integer.valueOf(4)

Provide warnings about improper attempts to synchronize on instances of any value-based classes in the Java platform. Run-time warnings for all such attempts, compile-time warnings when possible.

Sealed Classes (JEP 397)

Sealed classes and interfaces restrict which other classes may extend or implement them.

In Java, a class hierarchy enables the use of code via but we need to use it to model various possibles. When the class hierarchy is used in this way, it restricts the set of subclasses and can streamline the modeling.

A class is sealed by applying the sealed modifier then after any extends/implements clauses it specifies the classes that are permitted to extend the sealed class.

package com.example.sealedClasses;
public abstract sealed class Shape permits Circle, Rectangle, Square
{....}
// define Circle
// define Rectangle
// define Square

Sealed Classes impose 3 constraints on the sealed class on its permitted superclass. The sealed class and its permitted supplies must belong to the same module, if they are declared in an unnamed module they have to be in the same package and every permitted subclass must directly extend the sealed class and every permitted subclass must directly extend the sealed class must directly extent the sealed class and every permitted subclass must choose a modifier to describe how it continues.

package com.example.sealedClasses;
public abstract sealed class Shape permits Circle, Rectangle, Square {
 ....
}
public final class Circle extends Shape {
 ....
}
public sealed class Rectangle extends Shape permits TransparentRectangle, FilledRectangle {
 ....
}
public final class TransparentRectangle extends Rectangle {
 ....
}
public final class FilledRectangle extends Rectangle {
 ....
}
public non - sealed class Square extends Shape {
 ....
}

It could be final and allow no more subclassing. It could, in turn, be sealed which means it will have its own set of permitted subclasses or it could be a non-sealed one and only one of those modifiers final, sealed, or non-sealed must be used by each permitted subclass.

According to Oracle docs, sealed classes and interfaces restrict which other classes or interfaces may extend or implement them.

  • Allow the author of a class or interface to control which code is responsible for implementing it.
  • Provide a more declarative way than access modifiers to restrict the use of a superclass.
  • Support future directions in pattern matching by underpinning the exhaustive analysis of patterns.

Vector API (JEP 338)

Another new API with JDK16 will give developers a way of expressing computations that will reliably translate at runtime to vector hardware instructions on supported CPU architectures. Vector operations enable work to be done in a simple CPU cycle so that it can lead to a significant performance gain.

Note
This API can be used more efficiently by library developers to optimize common libraries, then developers can make use of this API.

According to Oracle docs, this API provides an initial iteration of an API to express vector computations that reliably compile at runtime to optimal vector hardware instructions on supported CPU architectures and thus achieve superior performance to equivalent scalar computations.

Allows taking advantage of the Single Instruction Multiple Data(SMD) instructions available on most modern CPUs. Although hotspot supports auto-vectorization the set of transformable scalar operations is limited and fragile to changes in the code. This API will allow developers to write complex vector algorithms in Java.

Example

Before After,

a = b + c * z[i+0] a b c z[i+0]

d = e + f * z[i+1] d e f z[i+1]

r = s + t * z[i+2] r s t z[i+2]

w = x + y * z[i+3] w x y z[i+3]

= +SIMD *SIMD

4 multiplications 1 SIMD multiplication

4 additions 1 SIMD addition

4 assignments 1 assignment

Foreign Linker API(JEP 389) and Foreign-Memory Access API(JEP 393)

According to Oracle docs, they introduce an API that offers statically-typed, pure-Java access to native code. This API will considerably simplify the otherwise error-prone process of binding to a native library.

Java has supported native method calls via the Java Native Interface(JNI) since Java 1.1 but it is hard and brittle.Java developers should be able to just use any native library that is deemed useful for a particular task.

Foreign Linker API provides foreign-function support without the need for any interviewing JNI glue code.

Foreign-Memory Access API allows Java Programs to safely and efficiently access foreign memory outside of the Java heap.

Summary

Thus, coming towards the end of this article, the basic aim is to know what’s new in Java 16 and how it will be helpful for developers.

What did we learn?

  • Pattern matching with instanceOf
  • Records and its use.
  • ZGC(Concurrent Thread-Stack Processing)
  • Elastic MetaSpace
  • Unix Domain Socket Channels
  • Packaging Tool
  • Value-Based Classes and Warnings
  • Sealed Classes
  • Vector API
  • Foreign Linker API
  • Foreign-Memory Access API

That’s all about new features in Java 16. I hope it gives some bonus to your skillset. Thanks for reading the article. Thanks.