What is new in Java 16
Java 16 reached General Availability on 16 March 2021, download Java 16 here.
Java 16 has 17 JEP items.
- 1. JEP 338: Vector API (Incubator)
- 2. JEP 347: Enable C++14 Language Features
- 3. JEP 357: Migrate from Mercurial to Git
- 4. JEP 369: Migrate to GitHub
- 5. JEP 376: ZGC: Concurrent Thread-Stack Processing
- 6. JEP 380: Unix-Domain Socket Channels
- 7. JEP 386: Alpine Linux Port
- 8. JEP 387: Elastic Metaspace
- 9. JEP 388: Windows/AArch64 Port
- 10. JEP 389: Foreign Linker API (Incubator)
- 11. JEP 390: Warnings for Value-Based Classes
- 12. JEP 392: Packaging Tool
- 13. JEP 393: Foreign-Memory Access API (Third Incubator)
- 14. JEP 394: Pattern Matching for instanceof
- 15. JEP 395: Records
- 16. JEP 396: Strongly Encapsulate JDK Internals by Default
- 17. JEP 397: Sealed Classes (Second Preview)
- Download Source Code
- References
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.
- A Vector processor processes multiple data at a time, known as single instruction, multiple data (SIMD).
- A Scalar processor processes only one data at a time, known as single instruction, single data (SISD).
Further Reading
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.
Further Reading
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:
- File size of version control system metadata (Mercurial) is too big.
- Available tooling
- Available hosting
Further Reading
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.
Further Reading
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
Further Reading
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.
Further Reading
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);
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.
$ javac --add-modules jdk.incubator.foreign CStrLen.java
warning: using incubating module(s): jdk.incubator.foreign
1 warning
Run with incubator modules enabled.
$ 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
.
$ 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
.
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.
$ javac --add-modules jdk.incubator.foreign JEP389.java
warning: using incubating module(s): jdk.incubator.foreign
1 warning
Run.
$ 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).
Further Reading
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.
package java.util;
@jdk.internal.ValueBased
public final class Optional<T> {
//...
}
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.
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.
$ 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.
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.
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.
# 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
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.
$ /opt/jep392/bin/JEP392
Output
The jpackage -h
is always your best friend:
$ /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).
Further Reading
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
Further Reading
15. JEP 395: Records
The record
is finalized and becomes a standard feature.
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
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.
Further Reading
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.
Further Reading
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
- OpenJDK 16 Project
- OpenJDK source code
- Wikipedia – Automatic Vectorization
- Auto Vectorization in Java
- Vector processor
- Scalar processor
- C++14 language features
- Wikipedia – Unix domain socket
- IntelliJ IDEA 2021.1 EAP 1: Support for Java 16
- OpenJDK – What is Metaspace
- Value-based Classes
- Data Classes and Sealed Types for Java
- Pattern Matching for Java
- OpenJDK Wiki – ZCG
- Java version history
Good information, thanks!
Nice