What changed in Java 17

Java 17LTS

Sealed classes, and JDK internals locked down

The LTS most teams migrated to after 8 and 11. Sealed classes completed the data-modelling trio with records and pattern matching, and strong encapsulation of JDK internals became the default rather than a warning.

Released 2021-09 · 3 features · 8 questions · 2 scenarios

Features

Sealed classes

standardJEP 409

A class or interface can declare exactly which types may extend or implement it, making the hierarchy closed and known to the compiler.

The problem it solved

A public abstract type could be extended by anyone, so no switch over its subtypes could ever be proven complete and no invariant across the hierarchy could be guaranteed.

How you did it before

Package-private constructors plus documentation, or an enum when the cases carried no data. Neither gave the compiler anything to check.

Journey: Preview in 15 (JEP 360) and 16, final in 17.

Asked as

  • What do sealed classes enable that abstract classes cannot?
  • How do sealed types, records and pattern matching work together?
  • Why must a sealed type's permitted subclasses be in the same module or package?

Scenario question

  • You are modelling the result of an operation as either a success with a value or one of three specific failures, and every call site must handle all four.

    How do you model it so a missed case cannot compile?

    What a good answer weighs

    A sealed interface with four record implementations, switched over with patterns and no default branch. The compiler then enforces exhaustiveness. Compare honestly with the alternatives — an enum plus a nullable payload, or exceptions — and say why algebraic modelling beats both when the cases carry different data.

Strongly encapsulate JDK internals

standardJEP 403

Reflective access to internal JDK classes is denied by default, with --add-opens or --add-exports required to override it.

The problem it solved

Libraries reached into JDK internals, which froze those internals in place and made every JDK upgrade risk breaking code that was never meant to have access.

How you did it before

Java 9 to 16 warned about illegal reflective access but permitted it, so most code kept working and most teams ignored the warning.

Asked as

  • Why does setAccessible fail on a JDK class now?
  • What did JPMS actually change for application developers?
  • What breaks when you move from Java 8 to 17 or 21?

Scenario question

  • A Java 8 application fails on 17 with InaccessibleObjectException from a serialization library that reflects into java.util.

    What are your options, in what order?

    What a good answer weighs

    First, upgrade the library — most have been fixed, and this is the only option that does not accumulate debt. If not possible, add a targeted --add-opens for the specific package and record why. The weak answer reaches for --add-opens first, or worse disables encapsulation wholesale, which re-freezes the internals the change was made to free.

Deprecate the Security Manager for removal

deprecatedJEP 411

The Security Manager was deprecated for removal, having been the primary sandboxing mechanism since Java 1.0.

The problem it solved

It was designed for untrusted applets, is extremely hard to configure correctly, imposed a permanent performance cost, and was almost never used correctly in server applications.

How you did it before

A policy file plus a Security Manager was the documented way to sandbox untrusted code in a JVM.

Asked as

  • What replaced the Security Manager for isolating untrusted code?
  • Why was a feature from Java 1.0 removed rather than fixed?

Other versions