Java™ 16 & 17
What's new and noteworthy?

Piotr Przybył
DevoxxFR, 29 IX MMXXI

© 2021 Piotr Przybył. Licensed under CC BY-NC-SA 4.0
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

$ whoami

Piotr Przybył
Software Gardener

$ who are you


A.K.A. Safe harbour statement: don't assume anything based on this presentation. Verify on your own. Errare humanum est.

Java 1️⃣6️⃣

  • released 2021-03-16
  • 17 JEPs in total
  • release notes
  • new syntax (records, pattern matching with instanceof)
  • preview features (sealed classes)
  • incubator modules (foreign mem access, foreign linker, vector API)
  • infrastructure (Git & GitHub)
  • new ports (Alpine Linux, Windows/AArch64)
  • and other features

JEPs per project

  • Amber: 394, 395, 397
  • Panama: 338, 389, 393
  • Valhalla: 390
  • Jigsaw: 396
  • still no Loom

Java 1️⃣6️⃣ JEPs:

  • 338: Vector API (Incubator)
  • 347: Enable C++14 Language Features
  • 357: Migrate from Mercurial to Git
  • 369: Migrate to GitHub
  • 376: ZGC: Concurrent Thread-Stack Processing
  • 380: Unix-Domain Socket Channels
  • 386: Alpine Linux Port
  • 387: Elastic Metaspace

Java 1️⃣6️⃣ JEPs:

  • 388: Windows/AArch64 Port
  • 389: Foreign Linker API (Incubator)
  • 390: Warnings for Value-Based Classes
  • 392: Packaging Tool
  • 393: Foreign-Memory Access API (Third Incubator)
  • 394: Pattern Matching for instanceof
  • 395: Records
  • 396: Strongly Encapsulate JDK Internals by Default
  • 397: Sealed Classes (Second Preview)

Java 1️⃣7️⃣ LTS

  • released 2021-09-14
  • 14 JEPs in total
  • release notes
  • new syntax (sealed classes)
  • preview features (pattern matching for switch)
  • incubator modules (foreign function & mem API, vector API)
  • new ports (macOS/AArch64)
  • and other features

Java 1️⃣7️⃣ JEPs:

  • 306: Restore Always-Strict Floating-Point Semantics
  • 356: Enhanced Pseudo-Random Number Generators
  • 382: New macOS Rendering Pipeline
  • 391: macOS/AArch64 Port
  • 398: Deprecate the Applet API for Removal
  • 403: Strongly Encapsulate JDK Internals
  • 406: Pattern Matching for switch (Preview)

Java 1️⃣7️⃣ JEPs:

  • 407: Remove RMI Activation
  • 409: Sealed Classes
  • 410: Remove the Experimental AOT and JIT Compiler
  • 411: Deprecate the Security Manager for Removal
  • 412: Foreign Function & Memory API (Incubator)
  • 414: Vector API (Second Incubator)
  • 415: Context-Specific Deserialization Filters

Thank you


Shall I migrate to Java X or stick to the latest LTS?

It depends

If your software runs on it, why not?

Maybe skip preview features in prod...

Migrating to nonLTS...

support cliff or de-facto LTS vendor

cloud providers

no preview features for others

need to re-compile preview features for next release

benefits from better performance, GCs, syntax, etc.

better feedback for Java Team

eating elephant in small pieces

The meaning, or not, of "LTS"

Neither nonLTS releases
nor preview features are

"monkey soft"

Preview features



More on preview features

Git & GitHub

introduced in 1️⃣6️⃣

JEP-357 & JEP-369
OpenJDK @GitHub

Enable C++14 Language Features

introduced in 1️⃣6️⃣

Allow the use of C++14 language features in JDK C++ source code

Build-time changes needed.

New builds

introduced in 1️⃣6️⃣

JEP 386: Alpine Linux Port
JEP 388: Windows/AArch64 Port

New builds

introduced in 1️⃣7️⃣

JEP 391: macOS/AArch64 Port

Warnings for Value-Based Classes

standard feature

introduced in 1️⃣6️⃣


Value-Based Classes

  • Classes, which should be compared by value (equals()), not identity(==)
  • "wrappers"
  • immutable
  • constructed factory methods, no constructors
  • freely substitutable when equal, so == isn't important
  • Value-based Classes

Value-Based Classes


  • java.lang.{Byte, Short, Integer,
    Long, Float, Double, Boolean, Character}
  • java.util.{Optional, ...}
  • java.time.{Instant, ZonedDateTime, Duration,...}
  • implementations of List.of(), List.copyOf(), Set.of(), ..., Map.entry()
  • and others annotated with jdk.internal.@ValueBased

Because of their nature, value objects should not be:

  1. compared using ==
  2. created using constructors
  3. used for synchronized(object)

This JEP is to make developers more aware of that and raise compiler and runtime errors when possible, to prepare for project Valhalla going GA.

  • constructors deprecated for removal
  • synchronization warnings emitted by javac when selected -Xlint:synchronization
  • HotSpot detects synchronized(valueBasedObject)
    • -XX:DiagnoseSyncOnValueBasedClasses=1 - fatal
    • -XX:DiagnoseSyncOnValueBasedClasses=2 - logging to console and JFR
  • use jdeprscan for 3rd party bytecode

Sealed Classes

standard feature in 1️⃣7️⃣


Sealed Classes

  • when we don't want someone else extend to our classes/implement interfaces
  • and we don't want to use final
  • and we don't want to reduce visibility from public
  • = prevent bad / unintended code reuse by inheritance

Sealed Classes

  • sealed Klass [permits Child1, Child2, Child3]
  • sealed Child1 [permits ...]
  • final Child2
  • non-sealed Child3
  • permits can be implicit in the same source file
  • the same module or package when no module
sealed classes

                sealed interface LibraryType
                	permits AbstractLibTypeImpl, NoOpLibTypeImpl {}

                sealed abstract class AbstractLibTypeImpl
                	implements LibraryType
                	permits LibTypeImpl1, LibTypeImpl2 {}

                final class LibTypeImpl1 extends AbstractLibTypeImpl {}
                final class LibTypeImpl2 extends AbstractLibTypeImpl {}

                final class NoOpLibTypeImpl implements LibraryType {}

            class UserLibTypeImpl
            	// this doesn't work
            	// extends AbstractLibTypeImpl implements LibraryType

            class SomeClass {
            	AbstractLibTypeImpl typeImpl;
            	void method(LibraryType libType) {}

3 'ities': overlapping, but not the same

  • visibility (public, protected, , private)
  • accessibility (modules)
  • extensibility (final | sealed classes)

Strongly Encapsulate JDK Internals

standard feature

introduced in 1️⃣7️⃣


Modules were introduced in Java 9 and brought warnings about illegal access.

Some suggested "these are just warnings, ignore them". Worse, some followed this "advice".

--illegal-access=permit was promised to be temporary.

In Java 16 --illegal-access=deny was default and deprecated.

What to do?

  • Stop using setAccessible(true)
  • set --illegal-access=debug|warn and start adding --add-opens
  • set --illegal-access=permit or don't upgrade to Java 16 and keep producing legacy code for future generations
Roses are red
reflection may hit
you shall not use
Illegal access in Java 16 A.K.A. 'My program crashes!'

More on migrating to --illegal-access=deny

1️⃣7️⃣ JEP-403

--illegal-access=... is no more!

Pattern Matching for instanceof

introduced in 1️⃣6️⃣


            if (object instanceof Integer) {
                Integer integer = (Integer) object;
                int doubled = integer * 2;

        if (object instanceof Integer integer) {
            int doubled = integer * 2;

A.K.A. Smart casting

            public static boolean nonEmptyString(Object obj) {
                return (obj instanceof String str) && !str.isEmpty();

Local variables from PM with instanceof

  • aren't implicitly final
  • visible only in the scope they're declared
  • shadow field names

            public static void whoAreYou(Object obj) {
                if (obj instanceof Serializable serializable) {
                    System.out.println("You're serializable " + serializable + "!");
                if (obj instanceof String string && string.length() >= 3) {
                    System.out.println("You're String, at least 3 characters long!");
                } else if (obj instanceof Integer integer && integer > 0) {
                    System.out.println("You're a positive Integer");
                } else if (obj instanceof Long aLong && (aLong < -9 || aLong > 9)) {
                    System.out.println("You're a Long with at least two digits");

Please make sure you don't implement equals in a wrong way.

How not to use (pattern matching with) instanceof

Pattern Matching for switch

🧪 preview feature in 1️⃣7️⃣


Pattern Matching for switch

Good old switch remains the same

Pattern Matching for switch

private static String getGreeting(Object version) {
    return switch (version) {
        case null -> throw new IllegalArgumentException("Impossible!");
        case Integer i && (i >= 17) -> "Hello, this is Java™ "+ i + " ;-)";
        case Integer i -> i +"? But how?";
        default -> "oops...";

Pattern Matching for switch

  • switch can be now more null friendly
  • switch handles now more than primitives, enum and String
  • dominant cases aren't allowed by compiler
  • cases can contain guards
  • sealed classes don't need default
  • pattern matching doesn't work with primitives
  • switch instruction works with PM too
  • PM doesn't allow fall-through


standard feature

introduced in 1️⃣6️⃣



new kind of type declaration

record is a restricted form of class

extends java.lang.Record

"transparent carrieds for immutable data"

record Complex(double real, double imaginary) {}

Records have

  • a name
  • record components ( ≥ 0)
  • which become private final fields
  • generated accessors
  • generated full canonical constructor
  • generated equals, hashCode, toString
  • body {}

Records can

  • (re-)define constructors: compact canonical, full canonical, custom
  • have own implementations of generated methods
  • (which should obey the invariants/rules)
  • have extra methods
  • have static fields & methods
  • implement interfaces
  • be generic

Records can't

  • extend classes or be extended
  • have setters*
  • have any "extra" instance fields
  • have "less visible" canonical constructors
  • declare native methods
  • assign components in compact constructors


  • are not Java Beans
  • are POJOs with accessors (without getters)
  • think "named tuples"!
  • sometimes require overriding equals() and hashCode()!

Nesting records

  • nesting records just like static classes
  • local records are very handy for streams, reduce and collectors as intermediate result type

Local declarations

As a by-product, interfaces and enums can be declared as local too (apart from records).

Reflection of records

Serialization of records

  • re-construction of objects using constructor
  • libraries and frameworks need to adapt...?


Annotations from components get "propagated" where their @Target(ElementType....)permits to.


Records don't have any copy() or with() method.

That's why it's important for accessors, equals() and hashCode() to obey contracts!

Using records with other features

  • already support PM with instanceof
  • and sealed hierarchies
  • in the future will support PM with deconstruction

More on records

ZGC: Concurrent Thread-Stack Processing

standard feature

introduced in 1️⃣6️⃣


ZGC: Concurrent Thread-Stack Processing

Move ZGC thread-stack processing from safepoints to a concurrent phase.
Remove all other per-thread root processing from ZGC safepoints.
Less than one millisecond should be spent inside ZGC safepoints on typical machines.

Elastic Metaspace

introduced in 1️⃣6️⃣


Elastic Metaspace


Packaging Tool

standard module

introduced in 1️⃣6️⃣


Packaging Tool

  • meant to allow building "native" packages for different platforms
  • no cross-build between platforms
  • no GUI (or splash screen), CLI only

Foreign-Memory Access API

incubator module

introduced in 1️⃣4️⃣, continued in 1️⃣6️⃣


and in 1️⃣7️⃣


Foreign-Memory Access API

  • avoid limitations of java.nio.ByteBuffer
  • be safe, unlike sun.misc.Unsafe
  • should perform equally well, better than JNI

Building blocks of FMAA

Foreign Linker API

incubator module

introduced in 1️⃣6️⃣


continued in 1️⃣7️⃣


Foreign Linker API

  • replace JNI with pure-Java development model
  • support for C (x64 & AArch64)
  • possibility to extend (C++, x86, ...)
  • performance >= JNI

CLinker allows

  • downcalls - e.g. calls from Java to native code
  • upcalls - e.g. calls from native back to Java code

Vector API

incubator module

introduced in 1️⃣6️⃣


continued in 1️⃣7️⃣


Vector API

  • platform agnostic API
  • currently supporting x86 and AArch64 at runtime
  • with option to support other architectures and Graal in the future
  • should use CPU extensions, e.g. SSE, AVX
  • degrading gracefully when not available

Vector API

Built around jdk.incubator.vector.Vector<E> and its subclasses.

There are numerous domains where this explicitly vectorizing API may be applicable such as machine learning, linear algebra, cryptography, finance, and usages within the JDK itself.
The Vector API will benefit significantly from value types once ready.

Enhanced Pseudo-Random Number Generators

standard feature in 1️⃣7️⃣


New RandomGenerator interface (and some new random algorithms), for cleaner approach and future extensibility.

Restore Always-Strict Floating-Point Semantics

standard feature in 1️⃣7️⃣


Now all floating point operations are strictfp.

Context-Specific Deserialization Filters

standard feature in 1️⃣7️⃣


Allow applications to configure context-specific and dynamically-selected deserialization filters via a JVM-wide filter factory that is invoked to select a filter for each individual deserialization operation.

For 🍎 users

Unix-Domain Socket Channels

standard feature

introduced in 1️⃣6️⃣


Unix-Domain Socket Channels

  • casting SocketAddress to InetSocketAddress will not always work now
  • works on Windows too
Provides support for Unix domain sockets (AF_UNIX) in the java.nio.channels, SocketChannel, and ServerSocketChannel classes.
how they massacred my boy


Some other stuff in Java 1️⃣6️⃣


Concurrently uncommit memory in G1

Support SHA-3 based signatures

Terminally deprecate ThreadGroup stop, destroy, isDestroyed, setDaemon and isDaemon

Some deprecated stuff in Java 1️⃣7️⃣

Some removed stuff in Java 1️⃣7️⃣

Some removed stuff in Java 1️⃣7️⃣




Always give feedback

Java™ 16 & 17
What's new and noteworthy?

Merci beaucoup !

Piotr Przybył