Java 17 Features: All You Need to Know

Photo of Mateusz Walczak

Mateusz Walczak

Updated Aug 3, 2023 • 10 min read
java_features

Java 17 reached general availability on 2021/09/14, which marked the day of the final release ready for production use.

It is a long-term support (LTS) release.

Each feature to be available for the next release must follow JDK Enhancement-Proposal & Roadmap Process. A complete summary for multiple Java versions is available in the JEP Index. I will focus on features just for version 17.

JEP 306: Restore Always-Strict Floating-Point Semantics

In JEP 306 feature, the previously mandatory parameter ‘strictfp’ to enable strict floating-point calculations has become optional.

Until the first Intel processors were shipped with SSE2 (Streaming SIMD Extensions 2) in 2001 that supported JVM strict floating-points operations in a straightforward manner, matching all cases of exact floating-points semantics required a lot of additional instructions. Currently both Intel and AMD support SSE2, so having a default floating-point semantic other than strict is no longer needed.

Running the following snippet of code:

package org.example.jep;

public class Main {

    public static strictfp double sum(double a, double b) {
        return a + b;
    }

    public static void main(String[] args) {
        double result = sum(5e10, 8e12);
        System.out.printf("Result: [%f].", result);
    }
}

Will print this warning in the console:


warning: [strictfp] as of release 17, all floating-point expressions are evaluated strictly and 'strictfp' is not required

JEP 356: Enhanced Pseudo-Random Number Generators


Pseudorandom number generators (PRNGs) are widely used, and in this feature, a new interface was added to simplify the usage of some of the LXM family of PRNG algorithms. This code snippet below shows an example on how to use it:

package org.example.jep;

import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;

public class Main {

    public static void main(String[] args) {
        RandomGenerator randomGenerator = RandomGeneratorFactory.of("L64X128StarStarRandom").create();
        System.out.printf("Result: [%d].", randomGenerator.nextInt());
    }
}

JEP 382: New macOS Rendering Pipeline


In JEP 382, a Java 2D internal rendering pipeline for macOS using the Apple Metal API is introduced as an alternative to the existing pipeline (which uses the deprecated Apple OpenGL API since 2018) was implemented.

JEP 391: macOS/AArch64 Port

JEP 391 introduces the port of JDK to macOS/AArch64. Apple plans to use its Apple Silicon in the future.

JEP 398: Deprecate the Applet API for Removal

In JEP 398, the java.applet.Applet was marked for removal. This interface was relevant for Java browser plug-ins, but nowadays most browsers removed the support for it.

@Deprecated(since = "9", forRemoval = true)
@SuppressWarnings("removal")
public class Applet extends Panel {
    // … 
}

JEP 403: Strongly Encapsulate JDK Internals


JEP 403 prevents access to the internal elements of the JDK. It is to ensure higher security and better maintainability.

% java --illegal-access=permit
Java HotSpot(TM) 64-Bit Server VM warning: Ignoring option --illegal-access=permit; support was removed in 17.0

If the command above was to succeed, it would allow access to nonpublic elements of Java (in versions from 9 to 16).

JEP 407: Remove RMI Activation


JEP 407 is about removing the java.rmi.activation package with all its classes and interfaces, for instance:

@Deprecated(forRemoval=true, since="15")
@SuppressWarnings("removal")
public final class ActivationDesc implements Serializable {
    // … 
}

JEP 409: Sealed Classes

JEP 409 introduces sealed classes and interfaces, which is useful for the way they are extended or implemented.

package org.example.jep;

public class Main {

    public static void main(String[] args) {
        Animal animal = new Dog();
    }

    private static final class Cat extends Animal {
    }

    private static final class Dog extends Animal {
    }

    private static sealed class Animal permits Dog, Cat {
    }
}

In the example above, the code compiles correctly, but if the sealed class is modified to:

private static sealed class Animal permits Cat {
}

Then the code does not compile and writes a message to the console.

error: class is not allowed to extend sealed class: Animal (as it is not listed in its permits clause)

JEP 410: Remove the Experimental AOT and JIT Compiler

JEP 410 removes the experimental Java-based ahead-of-time (AOT) and just-in-time (JIT) compiler. The documentation states that the compiler was rarely used, but the time to support and maintain it was significant, so following items were removed:

  • jdk.aot — the jaotc tool
  • jdk.internal.vm.compiler — the Graal compiler
  • jdk.internal.vm.compiler.management — Graal's MBean
  • src/hotspot/share/aot — dumps and loads AOT code
  • Additional code guarded by #if INCLUDE_AOT

JEP 411: Deprecate the Security Manager for Removal

In JEP 411 the security manager is marked as deprecated. There is no planned replacement for it. As per the JEP 411 document, “the Security Manager cannot address 19 of the 25 most dangerous issues identified by industry leaders in 2020”. It is required to address them individually in Java class libraries.

@Deprecated(since="17", forRemoval=true)
public class SecurityManager {
    // …
}

JEP 415: Context-Specific Deserialization Filters

JEP 415 adds new functionality that allows to create context-specific and dynamically-selected deserialization features. This addresses the security concern that when deserializing data, a security breach could happen. Fetching the data from untrusted sources could cause the execution of malicious code when data was deserialized. Filtering that during the deserialization is a step forward in security.

Preview feature

Preview features are newly proposed solutions. They may or may not exist in future releases. Their purpose is to test features with a wider audience and obtain feedback, propose changes, or introduce new approaches. To enable preview features use:

--enable-preview

Or enable the preview language level in your favourite IDE.

JEP 406: Pattern Matching for switch (Preview)

JEP 406 is mainly about extending the functionality of the ‘switch’ statement and extending the pattern’s functionality. The feature adds:

  • Integration of the ‘null’ test functionality in the switch itself
case null: break;
  • Convenient usage of the “->” (arrow) in switch statement
case null -> System.out.println("Oops");
  • Patterns in switch labels

case String s && (s.length() == 1) -> System.out.println("Success");

Incubator features

Incubator features were introduced in JEP 11 and they are candidates for future inclusion and remain under development. Similar to the preview items, they can be tested to gather feedback.

JEP 412: Foreign Function & Memory API (Incubator)

To enable Foreign Function & Memory API (Incubator):

--add-modules=jdk.incubator.foreign

Otherwise, this error will show up:

error: package jdk.incubator.foreign is not visible
import jdk.incubator.foreign.*;
                    ^
  (package jdk.incubator.foreign is declared in module jdk.incubator.foreign, which is not in the module graph)

In this feature, the ability to access the code outside of the Java runtime has been added. It’s a useful functionality when we have written code that isn’t Java and would like to invoke a function outside of JVM.

JEP 414: Vector API (Second Incubator)

To enable this feature add

--add-modules=jdk.incubator.vector

Otherwise this error will show up.

error: package jdk.incubator.vector is not visible
import jdk.incubator.vector.FloatVector;
                    ^
  (package jdk.incubator.vector is declared in module jdk.incubator.vector, which is not in the module graph)

This feature is being incubated for the second time, first introduced in JEP 338 as part of Java 16. For Java 17, its main focus is to improve the performance of the Vector API. The goals are to create a concise, platform-agnostic, and reliable API.

Summary

If you are starting a project from scratch and thinking about a Java version to use might want to consider Java 17, as it’s more secure and contains useful features. It’s also an LTS release that has a longer support period, so it might be considered a future proof option. To decide one must also think about dependencies in the project, if any of the frameworks planned to use support Java 17 release, etc.

For existing projects, it’s a bit more difficult to decide if it’s a good idea to migrate to Java 17. The existing components must be analyzed and some aspects need to be established or decided upon. How much time would it take to do this now? Are dependencies compatible? Can the infrastructure be deployed successfully? How many other components would need to be updated? Most importantly, how much would it cost to do that?

Changing to a newer version is a future-proof solution – the world continues to evolve and so does the technology sector. That said you need to verify if this is a good time for your project to migrate. In my opinion, if there are no compatibility issues and project constraints in sight, then moving to Java 17 might be worth it.

Photo of Mateusz Walczak

More posts by this author

Mateusz Walczak

Senior Java Developer at Netguru
Lost with AI?  Get the most important news weekly, straight to your inbox, curated by our CEO  Subscribe to AI'm Informed

Read more on our Blog

Check out the knowledge base collected and distilled by experienced professionals.

We're Netguru

At Netguru we specialize in designing, building, shipping and scaling beautiful, usable products with blazing-fast efficiency.

Let's talk business