Java 17 LTS: The Most Important New Features at a Glance
Java 17 LTS: The Most Important New Features at a Glance
On September 14, Oracle released Java 17 -- and for many Java developers, this is the release they have been waiting for over three years. Java 17 is the next Long-Term-Support release after Java 11, which we covered in detail in our Java 11 article. For teams that stick to LTS versions and skipped the intermediate releases 12 through 16, it is worth taking a close look at the accumulated new features.
Three Years, Six Releases
Since Java 9, a new Java version is released every six months -- as we already explained in our article on the Java 9 module system. Between Java 11 (September 2018) and Java 17 (September 2021), that means six intermediate releases. Each of them brought new features that often flew under the radar in the community, because many projects stay on LTS versions.
That is understandable -- nobody wants to run in production on a version that stops receiving security updates after six months. But it also means that Java 17 does not just bring the features from JDK 17 itself, but the cumulative innovations from versions 12 through 17. And those are substantial.
Sealed Classes: Controlled Inheritance
Sealed Classes are one of the highlights that matured over multiple releases (JEP 360, 375, 409) and reached final status in Java 17. The idea is simple but powerful: a class or interface can explicitly specify which classes are allowed to extend or implement it.
public sealed interface Shape
permits Circle, Rectangle, Triangle {
double area();
}
public final class Circle implements Shape {
private final double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
public final class Rectangle implements Shape {
private final double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
}
public non-sealed class Triangle implements Shape {
// non-sealed erlaubt weitere Unterklassen
private final double base, height;
public Triangle(double base, double height) {
this.base = base;
this.height = height;
}
@Override
public double area() {
return 0.5 * base * height;
}
}
The sealed keyword in combination with permits restricts the inheritance hierarchy. Each subclass must declare itself as final, sealed, or non-sealed. This allows the compiler to check whether all possible subtypes are covered -- a property that will show its strength especially in combination with pattern matching in switch expressions.
For modeling domain types, this is invaluable. Instead of an open class hierarchy where theoretically any class on the classpath can form a subclass, you define precisely which variants exist. Anyone familiar with algebraic data types from languages like Kotlin, Scala, or Haskell will recognize the pattern immediately.
Pattern Matching for instanceof
The second major feature that reaches final status in Java 17 (JEP 394, after previews in Java 14 and 15) eliminates a piece of boilerplate that has accompanied Java developers for decades:
// Vorher: klassisches instanceof mit explizitem Cast
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.length());
}
// Nachher: Pattern Matching -- Typ und Variable in einem Schritt
if (obj instanceof String s) {
System.out.println(s.length());
}
The variable s is directly available in the if block, correctly typed, and without a redundant cast. This also works with logical operators:
if (obj instanceof String s && s.length() > 5) {
System.out.println("Langer String: " + s);
}
This may seem like a small improvement at first glance. In practice -- especially in visitor patterns, event handlers, or deserialization logic -- it eliminates a significant amount of repetitive code.
Pattern Matching for switch (Preview)
As a preview feature, Java 17 delivers an even more powerful extension with JEP 406: pattern matching in switch expressions. In combination with Sealed Classes, this yields compact, exhaustive matching:
// Preview-Feature in Java 17
static String describe(Shape shape) {
return switch (shape) {
case Circle c -> "Kreis mit Radius " + c.getRadius();
case Rectangle r -> "Rechteck: " + r.getWidth() + " x " + r.getHeight();
case Triangle t -> "Dreieck mit Fläche " + t.area();
};
}
Because Shape is sealed and the compiler knows all permits classes, it can verify exhaustiveness -- no default branch is needed. This is a significant improvement over long if-else-instanceof chains, which were error-prone and hard to maintain.
Important: As a preview feature, it must be explicitly enabled with --enable-preview and is not yet intended for production use. The final version is expected to arrive in one of the upcoming releases.
Records and Text Blocks: Now Standard
Two features that were already in preview from Java 14 through 16 are now a permanent part of the language and are available for the first time to teams coming from Java 11:
Records (final since Java 16) are compact, immutable data classes:
public record Point(double x, double y) {}
var p = new Point(3.0, 4.0);
System.out.println(p.x()); // 3.0
System.out.println(p); // Point[x=3.0, y=4.0]
Constructor, getters, equals(), hashCode(), and toString() are generated automatically. For DTOs, value objects, and configuration objects, this replaces Lombok or hand-written boilerplate in many cases.
Text Blocks (final since Java 15) make multiline strings readable:
var json = """
{
"name": "encircle360",
"type": "software-consultancy",
"founded": 2017
}
""";
Anyone who regularly works with JSON, SQL, or HTML in Java code will not want to go without text blocks.
Other Notable Changes
Enhanced Pseudo-Random Number Generators (JEP 356)
Java 17 introduces a new RandomGenerator interface and several new algorithms available via RandomGeneratorFactory. For most applications, little changes, but those with statistical simulation or cryptographic requirements benefit from the expanded selection and unified API.
New macOS Rendering Pipeline (JEP 382)
On macOS, Java 17 uses the Apple Metal API instead of the deprecated OpenGL backend. For desktop applications on macOS, this brings better performance and future-proofing, since Apple marked OpenGL as deprecated starting with macOS 10.14.
Deprecation of the Security Manager (JEP 411)
The Security Manager -- originally designed for applets and barely used for years -- is marked as deprecated in Java 17. This signals that its final removal will follow in upcoming versions. For the vast majority of server applications, this has no impact, since the Security Manager was not activated there anyway.
Strong Encapsulation of JDK Internals (JEP 403)
What began with Java 9 and the module system is consistently enforced in Java 17: access to internal JDK APIs via reflection is blocked by default. The command-line option --illegal-access, which served as a bridge in earlier versions, no longer exists. Libraries and frameworks that accessed internal APIs have had to switch to public alternatives over the past three years -- and most have done so.
What Does This Mean for the Ecosystem?
Java 17 support in the framework ecosystem is encouragingly good. Spring Boot 2.5 and 2.6 run flawlessly on Java 17. Hibernate, Jackson, Testcontainers, and the common build tools already have compatible versions.
Particularly interesting for medium-term planning: the Spring team has announced that Spring Framework 6 and Spring Boot 3 will require Java 17 as a minimum. This is a clear signal that Java 17 will be the baseline in the enterprise Java ecosystem for years to come. Spring Boot 3 is expected to arrive in 2022 and will additionally complete the migration from javax.* to jakarta.* namespaces. Those who migrate to Java 17 now are well prepared for that.
Our Recommendation
At encircle360, we updated the first services to Java 17 in the week after the release. For teams running on Java 11 LTS, the migration is pleasantly straightforward -- significantly easier than the jump from Java 8 to 11. The biggest hurdle is typically the strong encapsulation of JDK internals (JEP 403). Those who cleaned up the --illegal-access warnings over the past three years should have few problems here.
A pragmatic migration plan:
- Install JDK 17 and integrate it into CI/CD -- we recommend Eclipse Temurin (formerly AdoptOpenJDK) or Amazon Corretto
- Compile and run tests -- most incompatibilities show up immediately
- Fix illegal access issues -- replace
--add-opensflags by updating the affected libraries - Set source level to 17 -- in the compiler plugin of Maven or Gradle
- Gradually introduce new features -- use Records, Sealed Classes, and Pattern Matching in new code
The combination of Sealed Classes, Records, and Pattern Matching changes the way you write Java domain models. It feels like a substantial leap in the expressiveness of the language -- with full backward compatibility. Java 17 is an excellent LTS release and will be the foundation for many teams in the years to come.
Written by
Patrick HütterFounder & Software Architect
Software architect, engineer and entrepreneur. Patrick has been building products and platforms for over a decade — from enterprise backends and cloud-native infrastructure to AI-powered applications. As founder of encircle360, he combines deep technical expertise with entrepreneurial vision, driving open source projects that create real impact.
You might also like
From Manifest to Production: How ADL, A2A and the Inference Gateway Are Revolutionizing Agent Infrastructure
Jul 5, 2026 · 12 min read
Agent Orchestration with Java: Bringing LLM Agents to Production on the JVM
Jul 4, 2026 · 6 min read
Spring AI: How Java Developers Can Finally Integrate AI Features the Right Way
Mar 25, 2026 · 5 min read