Part 1 of 14

Java 17: The LTS That Delivers — What Changed from Java 11

Java 17: The Landmark LTS

Java 17 was released on September 14, 2021 as a Long-Term Support (LTS) release. It is the successor to Java 11 (released September 2018) as the recommended production baseline for enterprise and cloud Java deployments.

Between Java 11 and Java 17, six non-LTS releases (Java 12 through 16) delivered a continuous stream of language improvements on a six-month cadence. Java 17 is where five of the most important new features — Records, Sealed Classes, Pattern Matching for instanceof, Text Blocks, and Switch Expressions — all reached their final, production-ready status simultaneously.

If your team is on Java 8 or Java 11, migrating to Java 17 is the single upgrade that gives you the largest set of language improvements in one supported, stable baseline.


Why Java 17 and Why Now?

LTS Guarantees

Oracle provides Java 17 with:

  • Premier support until September 2026
  • Extended support until September 2029

Eclipse Temurin (Adoptium), Amazon Corretto, and other OpenJDK builds follow similar long-term support windows.

Java 11 entered its extended support window in 2024. For teams still on Java 11, now is the right time to move.

Framework Requirements

The major Java frameworks now require Java 17 as their minimum:

FrameworkMinimum Java version
Spring Boot 3.xJava 17
Spring Framework 6.xJava 17
Hibernate 6.xJava 17
Quarkus 3.xJava 17
Micronaut 4.xJava 17
Jakarta EE 10Java 17

You cannot use Spring Boot 3 or Spring Framework 6 on Java 11. If you want the latest Spring ecosystem, Java 17 is the gate.

Security

Java 17 removes the Security Manager (deprecated) and RMI Activation (removed), and strongly encapsulates all JDK internal APIs. This closes years of attack surface that was exploitable via reflective access to JDK internals — a common vector in deserialization exploits.


The Feature Timeline: Java 12 → Java 17

Java 17 is an LTS, but its features arrived incrementally:

Java 12 (March 2019)

  • Switch Expressions — first preview (JEP 325)
  • String::indent, String::transform methods added
  • JVM Constants API (JEP 334)

Java 13 (September 2019)

  • Switch Expressions — second preview (JEP 354)
  • Text Blocks — first preview (JEP 355)

Java 14 (March 2020)

  • Switch Expressions — FINAL (JEP 361)
  • Records — first preview (JEP 359)
  • Pattern Matching for instanceof — first preview (JEP 305)
  • Helpful NullPointerExceptions (JEP 358) — exact null location in NPE messages
  • instanceof type checking improvements

Java 15 (September 2020)

  • Text Blocks — FINAL (JEP 378)
  • Records — second preview (JEP 384)
  • Sealed Classes — first preview (JEP 360)
  • Hidden Classes (JEP 371)
  • Remove Nashorn JavaScript Engine (JEP 372)
  • ZGC becomes production-ready (JEP 377)
  • Shenandoah GC becomes production-ready (JEP 379)

Java 16 (March 2021)

  • Records — FINAL (JEP 395)
  • Pattern Matching for instanceof — FINAL (JEP 394)
  • Sealed Classes — second preview (JEP 397)
  • Unix Domain Socket Channels (JEP 380)
  • Vector API — first incubator (JEP 338)
  • Foreign Memory Access API — third incubator
  • Stream.toList() shorthand

Java 17 (September 2021) — LTS

  • Sealed Classes — FINAL (JEP 409)
  • Pattern Matching for switch — first preview (JEP 406)
  • Enhanced Pseudo-Random Number Generators (JEP 356)
  • Strongly Encapsulate JDK Internals (JEP 403)
  • Context-Specific Deserialization Filters (JEP 415)
  • Foreign Function & Memory API — first incubator (JEP 412)
  • New macOS Rendering Pipeline (JEP 382)
  • macOS/AArch64 Port (JEP 391)
  • Restore Always-Strict Floating-Point (JEP 306)
  • Remove RMI Activation (JEP 407)
  • Deprecate Applet API (JEP 398)
  • Deprecate Security Manager (JEP 411)

All 14 JEPs in Java 17

JEPFeatureStatusImpact
306Restore Always-Strict Floating-Point SemanticsFinalLow
356Enhanced Pseudo-Random Number GeneratorsFinalMedium
382New macOS Rendering PipelineFinalmacOS only
391macOS/AArch64 PortFinalmacOS Apple Silicon
398Deprecate Applet API for RemovalDeprecatedLow
403Strongly Encapsulate JDK InternalsFinalHIGH
406Pattern Matching for switchPreviewMedium
407Remove RMI ActivationRemovedLow
409Sealed ClassesFinalHIGH
410Remove Experimental AOT and JIT CompilerRemovedLow
411Deprecate Security Manager for RemovalDeprecatedMedium
412Foreign Function & Memory APIIncubatorLow (preview only)
414Vector APIIncubatorLow (niche)
415Context-Specific Deserialization FiltersFinalSecurity-focused

Key Language Features in Depth

Records — Immutable Data Classes

Before Java 16, every data-carrying class required a constructor, accessors, equals(), hashCode(), and toString() — typically 30–50 lines of boilerplate per class.

// Java 11 — 40+ lines for a simple data class
public class Point {
    private final int x;
    private final int y;
    public Point(int x, int y) { this.x = x; this.y = y; }
    public int x() { return x; }
    public int y() { return y; }
    @Override public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Point)) return false;
        Point p = (Point) o;
        return x == p.x && y == p.y;
    }
    @Override public int hashCode() { return Objects.hash(x, y); }
    @Override public String toString() { return "Point[x=" + x + ", y=" + y + "]"; }
}

// Java 17 — one line
public record Point(int x, int y) {}

Records are immutable, provide canonical constructors, and cannot extend other classes. They are the foundation for the data-oriented programming style that pattern matching enables.

Sealed Classes — Closed Hierarchies

Sealed classes let you explicitly list all permitted subtypes:

public sealed interface Shape permits Circle, Rectangle, Triangle {}

public record Circle(double radius) implements Shape {}
public record Rectangle(double width, double height) implements Shape {}
public record Triangle(double base, double height) implements Shape {}

The compiler knows the complete set of subtypes, enabling exhaustive checks in switch expressions. You cannot have an unknown Shape implementation at runtime.

Text Blocks — Readable Multiline Strings

// Java 11 — JSON in code
String json = "{\n" +
    "  \"name\": \"Abhay\",\n" +
    "  \"role\": \"engineer\"\n" +
    "}";

// Java 17 — readable and maintainable
String json = """
    {
      "name": "Abhay",
      "role": "engineer"
    }
    """;

Text blocks automatically strip common indentation, handle escape sequences consistently, and make embedded SQL, HTML, JSON, and YAML readable in Java source.

Pattern Matching for instanceof

// Java 11 — check then cast
if (obj instanceof String) {
    String s = (String) obj;  // redundant cast
    System.out.println(s.length());
}

// Java 17 — pattern variable bound in one step
if (obj instanceof String s) {
    System.out.println(s.length());
}

The pattern variable s is in scope and type-safe within the if block. No cast, no ClassCastException risk.

Switch Expressions

// Java 11 — switch statement (fall-through risk)
String result;
switch (day) {
    case MONDAY:
    case TUESDAY:
        result = "Weekday";
        break;
    case SATURDAY:
    case SUNDAY:
        result = "Weekend";
        break;
    default:
        result = "Other";
}

// Java 17 — switch expression (no fall-through, returns a value)
String result = switch (day) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Weekday";
    case SATURDAY, SUNDAY -> "Weekend";
};

Switch expressions can be used anywhere an expression is expected, use arrow syntax to eliminate fall-through, and the compiler enforces exhaustiveness.


What Java 17 Does NOT Include

Java 17 is an LTS, not the last word. Several major features arrived in later releases:

FeatureRelease
Virtual Threads (Project Loom)Java 21
Structured ConcurrencyJava 21
Scoped ValuesJava 21
Sequenced CollectionsJava 21
Pattern Matching for switch — FinalJava 21
Record PatternsJava 21
Generational ZGCJava 21
Foreign Function & Memory API — FinalJava 22

If your primary goal is Virtual Threads and the reactive-free concurrency model, Java 21 is the target. Java 17 is the right target if you want a stable LTS with the language features your framework ecosystem requires today.


Java 17 vs Java 11 vs Java 21 — When to Use Which

SituationRecommended baseline
New project, greenfieldJava 21 (latest LTS)
Spring Boot 3.x requirementJava 17 minimum, Java 21 preferred
Strict LTS conservatismJava 17
Virtual Threads / massive concurrencyJava 21
Still on Java 8, single migration stepJava 17 (stable ecosystem)
Still on Java 11Java 17 or Java 21

Summary

Java 17 bundles five years of Java evolution into one LTS release:

  • Records — immutable data classes in one line
  • Sealed Classes — closed, compiler-known type hierarchies
  • Pattern Matching for instanceof — no more redundant casts
  • Text Blocks — readable multiline strings
  • Switch Expressions — switch as an expression with no fall-through
  • Strong JDK Encapsulation — security by default
  • Enhanced PRNGs — modern, pluggable random number generation
  • Deserialization Filters — per-context protection against gadget chains

What’s Next

Article 2: Setting Up Java 17 walks through installing the JDK, configuring Maven and Gradle, and setting up IntelliJ IDEA and VS Code for Java 17 development.