Main Tutorials

What is new in Java 16

Java 16 logo

Java 16 reached General Availability on 16 March 2021, download Java 16 here.

Java 16 has 17 JEP items.

Java 16 developer features.

jpackage, records (standard), pattern matching (standard), sealed types (second preview), foreign-memory access APIs (third incubator), foreign linker APIs to replace JNI (incubator), vector APIs (incubator)

1. JEP 338: Vector API (Incubator)

Java supports auto vectorization to optimize the arithmetic algorithms, which means the Java (JIT compiler) will transform some scalar operations (one item at a time) into vector operations (multiple items at a time) automatically; However, the developers have no control of this vector operation conversion, it totally depends on the JIT compiler to optimize the code, furthermore, not all scalar operations are transformable.

This JEP introduces new Vector APIs to allow developers to perform the vector operations explicitly.

2. JEP 347: Enable C++14 Language Features

This JEP allows the [C++ 14 features]((https://en.wikipedia.org/wiki/C%2B%2B14) to be used in the C++ source code within the JDK.

3. JEP 357: Migrate from Mercurial to Git

This JEP migrate the OpenJDK source code from Mercurial to Git or GitHub, relates to the below JEP 369

The reasons for migrating to Git:

  1. File size of version control system metadata (Mercurial) is too big.
  2. Available tooling
  3. Available hosting

4. JEP 369: Migrate to GitHub

This JEP joins the above JEP 357, migrate the OpenJDK source code from Mercurial to GitHub.

Further Reading

5. JEP 376: ZGC: Concurrent Thread-Stack Processing

This JEP improves the Z Garbage Collector (ZGC) by moving the ZGC thread-stack processing from safepoints to a concurrent phase.

History

  • Java 11 JEP 333 introduced the Z Garbage Collector (ZGC) as a experimental garbage collector.
  • Java 15 JEP 377, the ZGC became a product feature.

6. JEP 380: Unix-Domain Socket Channels

The Unix-domain sockets are used for inter-process communication (IPC) on the same host, which means exchanging data between processes executing on the same host. The Unix-domain sockets are similar to TCP/IP sockets except that they are addressed by filesystem pathnames rather than the Internet Protocol (IP) addresses and port numbers. Most Unix platforms, Windows 10 and Windows Server 2019, also supported the Unix-domain sockets.

This JEP add Unix-domain (AF_UNIX) socket support to the existing SocketChannel and ServerSocketChannel.

New Unix-domain Socket classes or APIs:

  • New socket address class, java.net.UnixDomainSocketAddress
  • New enum, java.net.StandardProtocolFamily.UNIX

7. JEP 386: Alpine Linux Port

This JEP port the JDK to Alpine Linux and other Linux distributions that use musl implementation. This JDK port enables Java to run out-of-the-box in Alpine Linux, which benefits those Java-dependent frameworks or tools like Tomcat and Spring.

P.S The Alpine Linux contains small image size, widely adopted in cloud deployments, microservices, and container environments.

Further Reading

8. JEP 387: Elastic Metaspace

Java 8 JEP 122 removed the PermGen (Permanent Generation), and introduced Metaspace, a native off-heap memory manager in the hotspot.

This JEP improves the metaspace memory management by returning unused HotSpot class-metadata or metaspace memory to the operating system more promptly, reducing the metaspace footprint, and simplifying the metaspace code.

Further Reading

9. JEP 388: Windows/AArch64 Port

This JEP port the JDK to Windows/AArch64, running JDK + Windows on ARM hardware, server, or ARM-based laptop.

P.S The Windows/AArch64 is a popular demand in the end-user market.

10. JEP 389: Foreign Linker API (Incubator)

This JEP enables Java code to call or can be called by native code written in other languages like C or C++, replace Java Native Interface (JNI)

P.S This is an incubating feature; need add --add-modules jdk.incubator.foreign to compile and run the Java code.

10.1 Below example shows how to use the foreign linker APIs to call the standard C library strlen to return the string’s length.


size_t strlen(const char *s);
CStrLen.java

import jdk.incubator.foreign.*;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;

import static jdk.incubator.foreign.CLinker.C_LONG;
import static jdk.incubator.foreign.CLinker.C_POINTER;

// Java call standard C library
// size_t strlen(const char *s);
public class CStrLen {

  public static void main(String[] args) throws Throwable {

      if (args.length == 0) {
          throw new IllegalArgumentException("Please provide an argument.");
      }

      String input = args[0];

      MethodHandle strlen = CLinker.getInstance().downcallHandle(
              LibraryLookup.ofDefault().lookup("strlen").get(),
              MethodType.methodType(long.class, MemoryAddress.class),
              FunctionDescriptor.of(C_LONG, C_POINTER)
      );

      try (MemorySegment str = CLinker.toCString(input)) {
          long len = (long) strlen.invokeExact(str.address()); // 5
          System.out.println(len);
      }

  }
}

Compile with incubator modules enabled.

Terminal

$ javac --add-modules jdk.incubator.foreign CStrLen.java

warning: using incubating module(s): jdk.incubator.foreign
1 warning

Run with incubator modules enabled.

Terminal

$ java --add-modules jdk.incubator.foreign -Dforeign.restricted=permit CStrLen mkyong

WARNING: Using incubator modules: jdk.incubator.foreign
6

10.2 Below is another example of calling a function defined in a C code.

A simple C function to print a hello world.


#include <stdio.h>

void printHello() {
        printf("hello world!\n");
}

Compile the above C code and output to a shared library hello.so.

Terminal

$ gcc -c -fPIC hello.c
$ gcc -shared -o hello.so hello.o

Below the Java program, find the hello.so and call its method printHello.

JEP389.java

import jdk.incubator.foreign.CLinker;
import jdk.incubator.foreign.FunctionDescriptor;
import jdk.incubator.foreign.LibraryLookup;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.nio.file.Path;
import java.util.Optional;

public class JEP389 {

  public static void main(String[] args) throws Throwable {

      Path path = Path.of("/home/mkyong/projects/core-java/java-16/hello.so");

      LibraryLookup libraryLookup = LibraryLookup.ofPath(path);

      Optional<LibraryLookup.Symbol> optionalSymbol = libraryLookup.lookup("printHello");
      if (optionalSymbol.isPresent()) {

          LibraryLookup.Symbol symbol = optionalSymbol.get();

          FunctionDescriptor functionDescriptor = FunctionDescriptor.ofVoid();

          MethodType methodType = MethodType.methodType(Void.TYPE);

          MethodHandle methodHandle = CLinker.getInstance().downcallHandle(
                  symbol.address(),
                  methodType,
                  functionDescriptor);
          methodHandle.invokeExact();

      }

  }
}

Compile.

Terminal

$ javac --add-modules jdk.incubator.foreign JEP389.java

warning: using incubating module(s): jdk.incubator.foreign
1 warning

Run.

Terminal

$ java --add-modules jdk.incubator.foreign -Dforeign.restricted=permit JEP389

WARNING: Using incubator modules: jdk.incubator.foreign
hello world!

History

  • Java 14 JEP 370 introduced Foreign-Memory Access API (Incubator).
  • Java 15 JEP 383 introduced Foreign-Memory Access API (Second Incubator).
  • Java 16 JEP 389 introduced Foreign Linker API (Incubator).
  • Java 16 JEP 393 introduced Foreign-Memory Access API (Third Incubator).
  • Java 17 JEP 412 introduced Foreign Function & Memory API (Incubator).

11. JEP 390: Warnings for Value-Based Classes

This JEP provides a new warning if we synchronize instances of value-based classes; Also deprecating the primitive wrapper class (value-based) constructors for removal.

11.1 How to identify value-based classes?
The annotation @jdk.internal.ValueBased tells if a class is a value-based class. Review the following two classes, and we can tell both the primitive wrapper class Double and Optional are value-based classes.

Optional.java

package java.util;

@jdk.internal.ValueBased
public final class Optional<T> {
  //...
}
Double.java

package java.lang;

@jdk.internal.ValueBased
public final class Double extends Number
        implements Comparable<Double>, Constable, ConstantDesc {

  //...
}

Note
Refer JEP 390: Warnings for Value-Based Classes for complete list of value-based classes.

11.2 Below example try to synchronized a value-based class.

JEP390.java

public class JEP390 {

    public static void main(String[] args) {

        Double d = 20.0;
        synchronized (d) {} // javac warning & HotSpot warning
    }
}

Compile the above code and hits the new warning.

Terminal

$ javac JEP390.java
JEP390.java:7: warning: [synchronization] attempt to synchronize on an instance of a value-based class
        synchronized (d) {} // javac warning & HotSpot warning
        ^
1 warning

11.3 Java 9 deprecated the primitive wrapper class (value-based) constructors and is now marked for removal.

Double.java

package java.lang;

//...

@jdk.internal.ValueBased
public final class Double extends Number
        implements Comparable<Double>, Constable, ConstantDesc {

  @Deprecated(since="9", forRemoval = true)
  public Double(double value) {
      this.value = value;
  }

  @Deprecated(since="9", forRemoval = true)
  public Double(String s) throws NumberFormatException {
      value = parseDouble(s);
  }

  //...
}

Further Reading

Is this about the value types in the future release?

12. JEP 392: Packaging Tool

The JEP move the jpackage tool from jdk.incubator.jpackage to jdk.jpackage, and became a standard or product feature in Java 16. This jpackage is a packaging tool to package Java application into a platform-specific package like:

  • Linux: deb and rpm
  • macOS: pkg and dmg
  • Windows: msi and exe

History

  • Java 14 JEP 343 introduced an jpackage incubating tool and it remained an incubating tool in Java 15.

12.1 Below example shows the use of jpackage to package a simple Java Swing program into a deb format in the Linux system (Ubuntu).

A simple Java Swing program to display a hello world.

JEP392.java

import javax.swing.*;
import java.awt.*;

public class JEP392 {

    public static void main(String[] args) {

        JFrame frame = new JFrame("Hello World Java Swing");
        // display frame site
        frame.setMinimumSize(new Dimension(800, 600));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // center the JLabel
        JLabel lblText = new JLabel("Hello World!", SwingConstants.CENTER);
        // add JLabel to JFrame
        frame.getContentPane().add(lblText);

        // display it
        frame.pack();
        frame.setVisible(true);

    }
}

Create a jar file and jpackage it into a platform-specific package; since this is tested in an Ubuntu system, it will create a .deb file.

Terminal

# compile
$ javac JEP392.java

# create a jar file
$ jar cvf hello.jar JEP392.class

# package the jar file into platform-specific package
$ /opt/jdk-16/bin/jpackage -i . -n JEP392 --main-jar hello.jar --main-class JEP392

# The jpackage created this jep392_1.0-1_amd64.deb
$ ls -lsah
4.0K -rw-rw-r--  1 mkyong mkyong  994 Mac  15 13:52 hello.jar
 30M -rw-r--r--  1 mkyong mkyong  30M Mac  15 14:01 jep392_1.0-1_amd64.deb

Install the .deb file;

Terminal

sudo dpkg -i jep392_1.0-1_amd64.deb
Selecting previously unselected package jep392.
(Reading database ... 225576 files and directories currently installed.)
Preparing to unpack jep392_1.0-1_amd64.deb ...
Unpacking jep392 (1.0-1) ...
Setting up jep392 (1.0-1) ...

$ ls -lsah /opt/jep392/bin/JEP392
1.6M -rwxr-xr-x 1 root root 1.6M Mac  15 14:01 /opt/jep392/bin/JEP392

The default installation directory on

  • Linux is /opt
  • macOS is /Applications
  • Windows is C:\Program Files\

P.S This can be overridden via the jpackage --install-dir option.

Run the installed Java Swing program.

Terminal

$ /opt/jep392/bin/JEP392

Output

hello world swing

The jpackage -h is always your best friend:

Terminal

$ /opt/jdk-16/bin/jpackage -h
Usage: jpackage <options>

Sample usages:
--------------
  Generate an application package suitable for the host system:
      For a modular application:
          jpackage -n name -p modulePath -m moduleName/className
      For a non-modular application:
          jpackage -i inputDir -n name \
              --main-class className --main-jar myJar.jar
      From a pre-built application image:
          jpackage -n name --app-image appImageDir
  Generate an application image:
      For a modular application:
          jpackage --type app-image -n name -p modulePath \
              -m moduleName/className
      For a non-modular application:
          jpackage --type app-image -i inputDir -n name \
              --main-class className --main-jar myJar.jar
      To provide your own options to jlink, run jlink separately:
          jlink --output appRuntimeImage -p modulePath -m moduleName \
              --no-header-files [<additional jlink options>...]
          jpackage --type app-image -n name \
              -m moduleName/className --runtime-image appRuntimeImage
  Generate a Java runtime package:
      jpackage -n name --runtime-image <runtime-image>

  //...

Further Reading

13. JEP 393: Foreign-Memory Access API (Third Incubator)

The Foreign-Memory Access APIs allow Java API to access the foreign memory outside of the Java heap, such as memcached, Lucene, etc.

This JEP updated the Foreign-Memory access APIs and remained as the incubator module.

History

  • Java 14 JEP 370 introduced Foreign-Memory Access API (Incubator).
  • Java 15 JEP 383 introduced Foreign-Memory Access API (Second Incubator).
  • Java 16 JEP 389 introduced Foreign Linker API (Incubator).
  • Java 16 JEP 393 introduced Foreign-Memory Access API (Third Incubator).
  • Java 17 JEP 412 introduced Foreign Function & Memory API (Incubator).

14. JEP 394: Pattern Matching for instanceof

The pattern matching for instanceof is a standard or product feature in Java 16.

Before pattern matching, we check the object’s type and cast to a variable manually.


if (obj instanceof String) {
    String s = (String) obj;    // cast
}

Now we can heck the object’s type and cast it automatically


if (obj instanceof String s) {
    //... s is a string
}

For example, below is a common check and cast example.


  if (obj instanceof String) {
      String s = (String) obj;
      if (s.length() > 5) {
          if (s.equalsIgnoreCase("java16")) {
              //...
          }
      }
  }

And, we can refactor the above code using the new instanceof.


  if (obj instanceof String s && s.length() > 5) {
      if (s.equalsIgnoreCase("java16")) {
          //...
      }
  }

History

  • Java 14 JEP 305, first preview.
  • Java 15 JEP 375, second preview.
  • Java 16, standard feature.

15. JEP 395: Records

The record is finalized and becomes a standard feature.

JEP395.java

package com.mkyong.java16.jep395;

public class JEP395 {

    record Point(int x, int y) { }

    public static void main(String[] args) {

        Point p1 = new Point(10, 20);
        System.out.println(p1.x());         // 10
        System.out.println(p1.y());         // 20

        Point p2 = new Point(11, 22);
        System.out.println(p2.x());         // 11
        System.out.println(p2.y());         // 22

        Point p3 = new Point(10, 20);
        System.out.println(p3.x());         // 10
        System.out.println(p3.y());         // 20

        System.out.println(p1.hashCode());  // 330
        System.out.println(p2.hashCode());  // 363
        System.out.println(p3.hashCode());  // 330

        System.out.println(p1.equals(p2));  // false
        System.out.println(p1.equals(p3));  // true
        System.out.println(p2.equals(p3));  // false

    }
}

History

  • Java 14 JEP 359, first preview.
  • Java 15 JEP 384, second preview.
  • Java 16, standard feature.

Further Reading

16. JEP 396: Strongly Encapsulate JDK Internals by Default

Java 9 JEP 261 introduced the --illegal-access option to control the access of the internal APIs and packaged of the JDK.

This JEP change the default mode of --illegal-access option from permit to deny. With this change, the internal packages and APIs (except the critical internal APIs) of the JDK will no longer open by default.

This JEP’s motivation is to discourage the third-party libraries, frameworks, and tools from using the internal APIs and packages of the JDK.

17. JEP 397: Sealed Classes (Second Preview)

Java 15 JEP 360 introduced sealed classes and interfaces to restrict which class can extend or implement them. This JEP is the second preview with some improvements.

P.S This sealed class is a standard feature in Java 17.

Download Source Code

$ git clone https://github.com/mkyong/core-java

$ cd java-16

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Prasad Honrao
2 years ago

Good information, thanks!

Kicha
3 years ago

Nice