Java 16 – New Features and Improvements + Deprecated and Removed APIs + Example

  • In this article we will learn about New Features in Java 16 along with deprecated/removed features and APIs.
  • In simple words, Java 16 is a major feature (17 new feature) release and it has brought many JVM specific changes and language specific changes to JAVA. It followed the Java release cadence introduced Java 10 onwards and it was released on Mar 2021 (just six months after Java 15 release).
  • Java 16 is a non-LTS (non – Long Term Support) release.
  • We will discuss each feature in detail with the help of example. Let’s have a summary of all the features along with version.
Java 8, Java 9, Java 10, Java 11, Java 12, Java 13, Java 14, java 15, Java 16 and so on ...
Issues Fixed in JDK 16 per organization

Record Classes (JEP 384 | JEP 395)

  • The record class was introduced in Java 14 as preview feature. In Java 16, the record classes are adopted as permanent language feature. The record is a kind of type declaration like enum. It is used for “plain data carriers” classes that contain data not meant to be altered and only the most fundamental methods such as constructors and accessors. The record classes can also be created as local record within a method, same as local classes.

record Rectangle(int length, int width) { }

public class MyApp {
  public static void main(String[] args) {
	Rectangle rec = new Rectangle(12, 5);
	System.out.println(rec.length()); //12
	System.out.println(rec.width()); //5
        //local record class
	record Employee(String name, int age) { }
	Employee emp = new Employee("Petter", 22);
	System.out.println(; //Petter
	System.out.println(emp.age); //22

Pattern Matching for instanceof Operator (JEP 361)

  • The instanceof operator has been changed for pattern matching of an object to make code more concise and robust. This feature was introduced in Java 14 as preview feature. In Java 16, this feature has been adopted as permanent language feature. For example code as below.
if (animal instanceof Cow) {
  Cow a = (Cow) animal;

Now with the new instanceof, we can write above code as below.

if (animal instanceof Cow a) {

Complete Example: instanceof Operator


interface Animal {

class Cow implements Animal {
  String name;

  public Cow(String name) { = name;

  public String getCowName() {
	return name;

class Horse implements Animal {
  String name;

  public Horse(String name) { = name;

  public String getHorseName() {
	return name;

public class MyApp {
  public static void main(String[] args) {
	Animal ob = new Cow("Cow");
  static String getName(Animal animal) {
	if (animal instanceof Cow a) {
	} else if (animal instanceof Horse a) {
	return null;

Sealed Classes (JEP 360 | JEP 397)

  • Sealed classes and interfaces were introduced in Java 15 as preview feature. In Java 16 they are previewed again as JEP 397 – Sealed Classes (Second Preview). A sealed class is a class that can be inherited by only specified classes. For example.
public sealed class Animal
               permits Cow, Dog{

A sealed class is created using sealed keyword. The above sealed class Animal can only be extended by Cow and Dog classes.

public class Cow implements Animal {

public class Dog implements Animal {

Day Period Support Added to java.time Formats (JDK-8247781)

  • A new formatter pattern, letter ‘B‘ has been added to translate day period in below classes.

If the local time is morning time, the output will be as ‘in the morning’.

String time = DateTimeFormatter.ofPattern("B").format(;

Note: Suppose current time is 11:50 PM, then output will be 'at night'.

Stream.toList() Method Added (JDK-8180352)

In Java 16, a new default method toList() added to Stream interface as following – The Stream::toList accumulates the elements of this stream into a List.


public static void main(String[] args) {
 Stream<String> stream = Stream.of("A", "B", "C");
 List<String> strList = stream.toList();
 System.out.println(strList.size()); // 3

 IntStream intStream = IntStream.of(10, 12, 15, 20);
 List<Integer> intList = intStream.boxed().toList();
 System.out.println(intList.size()); // 4 

Note: The Stream::toList is the replacement of using Collectors.toList() to convert stream into list. For example as below.

List<String> strList = stream.collect(Collectors.toList());
List<Integer> intList = intStream.boxed().collect(Collectors.toList()); 

JEP 338 – Vector API (Incubator)

  • New Vector APIs introduced allowing developers to perform the vector operations explicitly.

JEP 347 – Enable C++14 Language Features

  • C++ 14 features can be used in c++ source code with the JDK 16.

JEP 357 | JEP 369 – Migrate from Mercurial to Git/GitHub

  • OpenJDK source code is moved from mercurial to Git/GitHub

JEP 376 – ZGC – Concurrent Thread-Stack Processing

  • Z Garbage Collector improved by moving its thread-stack processing from safepoints to concurrent phase.

JEP 380 – Unix-Domain Socket Channels

  • SocketChannel and ServerSocketChannel now supports Unix Domain sockets.

JEP 386 – Alpine Linux Port

  • Now JDK is available for Alpine Linux and other Linux distributions which use musl implementation.

JEP 387 – Elastic Metaspace

  • Metaspace memory management is improved by returning unused HotSpot class-metadata or metaspace memory to the operating system quickly, reduces the metaspace footprint, and simplify the metaspace code.

JEP 388 – Windows/AArch64 Port

  • Now JDK can run on AArch64, on ARM hardware server or ARM based laptops.

JEP 389 – Foreign Linker API (Incubator)

  • Java code can be called by C/C++ or vice versa using new API replacing the JNI.

JEP 390 – Warnings for Value-Based Classes

  • Warnings are raised in case of value-based classes are synchronised using synchronize.

JEP 392 – Packaging Tool

  • Java 14 provided jpackage as incubating tool for packaging self-contained Java applications. It remained an incubating tool in Java 15. Now in Java 16, it is promoted from incubation to a production-ready feature and hence the jdk.incubator.jpackage is changed to jdk.jpackage package.

JEP 393 – Foreign-Memory Access API (Third Incubator)

  • Minor enhancements to Foreign Memory Access API.

JEP 396 – Strongly Encapsulate JDK Internals by Default

  • default mode of –illegal-access option is now deny. Earlier it was permit.

Java 16 – value-based class ( java.util.Optional and java.time.LocalDateTime)

  • Some classes, such as java.util.Optional and java.time.LocalDateTime, are value-based. Note instances of a value-based class are final and immutable. Such classes have annotation @jdk.internal.ValueBased and Java 16 now generates compile time warnings in case such classes are synchronized using synchronized keyword. Wrapper classes are value based. For example, Double class is a value based. For Example:
package java.lang;
public final class Double extends Number
   implements Comparable<Double>, Constable, ConstantDesc {

Let’s try to synchronized the Double.

public class TestValueBasedExample {
   public static void main(String[] args) {
      Double d = 10.0;
      synchronized (d) {

Compile and Run the program ($javac warning: [synchronization] attempt to synchronize on an instance of a value-based class
   synchronized (d) {
1 warning

Java 16 – Deprecated APIs

  • ThreadGroup methods like stop, destroy, isDestroyed, setDaemon and isDaemon methods are deprecated and will be removed in future release. These API/mechanism to destroy a threadgroup is flawed and such method which supports explicitly or automatically destroying a thread group are terminally deprecated.
  • Signal Chaining APIs like sigset, signal are obsolete and their use is deprecated. sigaction is cross-platform and is supported API for multi-threaded processes.
  • APIs representing DNs as Principal or String objects are deprecated.
  • elliptic curves which are either obsolete or not implemented using modern formulas and techniques of SunEC provider are removed.

Java 16 – Removed APIs

  • The non-public class java.awt.PeerFixer is removed. Its purpose was to provide deserialization support of ScrollPane objects created prior JDK 1.1.1.
  • jaotc, an experimental Java Ahead-of-Time compilation tool is removed. Experimental Java-based JIT compiler, Graal, is also removed.
  • root certificates with weak 1024-bit RSA public keys have been removed from the cacerts keystore.

References (More Details)

JDK 16 Release Notes
Java Language Updates

Thank you so much for your time. Keep learning as usual 🙂