Java 25 is now generally available as the latest Long-Term Support (LTS) release, bringing a wealth of improvements in language expressiveness, performance, and developer productivity. Released on September 16, 2025, Java 25 arrives 30 years after Java's inception and continues to evolve the platform in significant ways.
This release delivers 18 JDK Enhancement Proposals (JEPs) covering everything from syntactic sugar to JVM optimizations. Many features were incubating or in preview in earlier versions and are now finalized, while others remain in preview or incubator status.
Table of Contents
- Language Enhancements
- Concurrency and Threading
- Performance and Memory
- Runtime and JIT Optimizations
- Garbage Collection
- Observability and Profiling
- Security Enhancements
- Platform Changes
Language Enhancements
Primitive Types in Patterns (Third Preview, JEP 507)
One long-awaited language enhancement is the ability to use primitive types in pattern matching constructs. In Java 25, the third preview of this feature allows primitive type patterns in all pattern contexts and extends instanceof
and switch
to work with any primitive types.
Why it's useful:
- Perform pattern matching on primitives without manual boxing or conversions
- Switch on an Object can now directly match cases like
case int i:
orcase double d:
- Eliminates boilerplate and reduces ClassCastException risks
Example:
// Enable with --enable-preview
Object value = 42;
switch (value) {
case int i -> System.out.println("Integer: " + i);
case double d -> System.out.println("Double: " + d);
case String s -> System.out.println("String: " + s);
default -> System.out.println("Other type");
}
Development Impact:
This is still in preview but signals cleaner pattern matching logic. Especially useful for code interfacing with numeric data from AI models or external libraries.
Module Import Declarations (JEP 511)
Java 25 finalizes Module Import Declarations, allowing you to import entire modules with a single statement using import module <module.name>;
.
Example:
import module java.base; // Imports all of java.base (java.util, java.lang, etc.)
public class Example {
public static void main(String[] args) {
List<String> list = new ArrayList<>(); // No explicit imports needed
System.out.println("Hello World");
}
}
Why it matters:
- Simplifies reuse of modular libraries
- Great for scripting, learning, or quick prototypes
- Reduces import clutter without requiring your code to be modular
Development Impact:
Ideal for small programs and educational settings, though explicit class imports remain clearer for large codebases.
Compact Source Files and Instance Main Methods (JEP 512)
Java becomes friendlier to newcomers with simplified syntax for single-file programs.
Example:
// No class declaration needed - just save as Hello.java
void main() {
IO.println("Hello, Java 25!"); // New IO class for simple output
}
Key features:
- No
public static void main(String[] args)
boilerplate required - Top-level statements wrapped in a class automatically
- New
java.lang.IO
class with convenient I/O methods
Why it matters:
Dramatically reduces ceremony for small programs. Beginners can write "Hello World" without understanding classes, public static, or command-line arguments.
Flexible Constructor Bodies (JEP 513)
Java 25 lifts the restriction that constructor calls to super()
or this()
must be the first statement, allowing certain code to execute beforehand.
Example:
class Square extends Shape {
Square(int side) {
if (side < 0) side = 0; // Validate input before super()
super(side, side); // Call superclass constructor
}
}
Why it matters:
- Enables natural constructor logic with input validation
- Prevents errors by ensuring proper values reach the superclass
- Removes need for awkward workarounds
Important: You still cannot reference instance fields or methods before the super()
call completes.
Concurrency and Threading
Structured Concurrency (Fifth Preview, JEP 505)
Structured Concurrency continues evolving from Project Loom, treating related threads as a single unit of work with controlled lifecycle management.
Example:
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<Data> task1 = scope.fork(() -> fetchData());
Future<Analysis> task2 = scope.fork(() -> analyze());
scope.join(); // Wait for all tasks
scope.throwIfFailed(); // Propagate exceptions if any
// Use task1.resultNow() and task2.resultNow()
}
Benefits:
- Child tasks can't outlive their scope
- Automatic cancellation if one task fails
- Improved observability and debugging
- Perfect for AI/ML pipelines with concurrent inference tasks
Scoped Values (JEP 506)
Now finalized in Java 25, Scoped Values provide a safe, efficient way to share immutable data within and across threads, replacing ThreadLocal in many scenarios.
Example:
static final ScopedValue<String> USER_ID = ScopedValue.newInstance();
public void handleRequest(Request req) {
String userId = authenticate(req);
ScopedValue.where(USER_ID, userId).run(() -> {
processRequest(); // Any method called here can access USER_ID
});
}
void processRequest() {
String currentUser = USER_ID.get(); // Available even in different threads
// ... use currentUser ...
}
Why it's better than ThreadLocal:
- No memory leaks (values automatically cleared when scope ends)
- Lower overhead, especially with virtual threads
- Immutable and thread-safe by design
- Clear scope boundaries
Performance and Memory
Stable Values (Preview, JEP 502)
A brand-new preview feature introducing an API for lazily-initialized immutable values that can be set exactly once.
Example:
import jdk.internal.vm.StableValue;
public class ConfigHolder {
private final StableValue<Settings> settings = StableValue.of();
public Settings getSettings() {
return settings.orElseSet(this::loadSettingsFromDatabase);
}
}
Key benefits:
- Thread-safe lazy initialization without double-checked locking
- JVM treats stable values as constants for optimization
- Better startup performance by deferring expensive computations
- Utilities for stable collections with on-demand element computation
Vector API (Tenth Incubator, JEP 508)
The Vector API continues its evolution, now in its 10th incubator iteration, enabling SIMD operations for high-performance computing.
Example:
FloatVector vecA = FloatVector.fromArray(FloatVector.SPECIES_256, arr1, 0);
FloatVector vecB = FloatVector.fromArray(FloatVector.SPECIES_256, arr2, 0);
FloatVector vecC = vecA.add(vecB); // Vectorized addition
vecC.intoArray(result, 0);
Improvements in Java 25:
- Now uses Foreign Function & Memory API for better maintainability
- Support for 16-bit float (Float16) auto-vectorization
- Enhanced performance for AI inference and scientific computing
Compact Object Headers (JEP 519)
Now a production feature (was experimental in JDK 24), reducing object header size from 96-128 bits to a fixed 64 bits on 64-bit platforms.
Benefits:
- Significant memory savings for applications with many small objects
- Better cache utilization and reduced memory bandwidth usage
- Improved GC efficiency with smaller heap footprint
- Automatic optimization requiring no code changes
Runtime and JIT Optimizations
Ahead-of-Time Command-Line Ergonomics (JEP 514)
Simplifies the AOT compilation workflow by streamlining command-line options and processes.
Why it matters:
- Reduces startup time by pre-compiling classes/methods to native code
- Makes AOT easier to use for common cases
- Part of Project Leyden's effort to tackle startup and warm-up times
Ahead-of-Time Method Profiling (JEP 515)
Introduces a mechanism where the JVM can use method execution profiles from training runs to optimize JIT compilation on startup.
How it works:
- Run application with profiling to collect method hotspot data
- Store profile data in AOT cache
- On subsequent startups, JIT immediately optimizes known hot methods
Benefits:
- Faster time to peak performance
- Reduced warm-up phase
- Particularly valuable for short-lived processes or after service restarts
Garbage Collection
Generational Shenandoah (JEP 521)
The generational mode for Shenandoah GC is now a production feature (no longer experimental).
Key improvements:
- Splits heap into young and old generations for better efficiency
- Improved throughput and reduced pause times
- Better handling of allocation spikes
- Enable with
-XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational
When to use:
Ideal for applications requiring ultra-low pause times with better throughput characteristics than the single-generation mode.
Observability and Profiling
JFR CPU-Time Profiling (Experimental, JEP 509)
Java Flight Recorder gains CPU-time profiling capabilities on Linux, measuring actual CPU time consumed by threads rather than just sampling call stacks.
Benefits:
- More accurate profiling not skewed by blocked/waiting threads
- Better identification of CPU-bound bottlenecks
- Complements existing JFR sampling with precise CPU usage data
JFR Cooperative Sampling (JEP 518)
Improves JFR's stack trace collection by making threads cooperate during sampling, avoiding conflicts with running code.
Improvements:
- More stable and accurate profiling data
- Lower overhead and reduced risk of sampling conflicts
- Better reliability in high-stress production environments
JFR Method Timing & Tracing (JEP 520)
Enables recording execution times and stack traces for specific methods without code modification.
Example usage:
# Configure method tracing via JFR
jcmd <pid> JFR.configure methodPattern="com.example.*.processTransaction"
Benefits:
- Target specific methods for detailed performance analysis
- No need to redeploy or instrument code
- Minimal performance impact compared to external profilers
Security Enhancements
PEM Encodings of Cryptographic Objects (Preview, JEP 470)
Java 25 introduces built-in support for PEM format encoding/decoding of cryptographic objects.
Example:
// Hypothetical API (preview)
String pemKey = PEMEncoder.encode(privateKey);
PrivateKey key = PEMDecoder.decodePrivateKey(pemString);
Why it matters:
- Eliminates need for external libraries like BouncyCastle for PEM handling
- Simplifies integration with OpenSSL tools and certificate management
- Essential for modern security workflows and hardware token integration
Key Derivation Function API (JEP 510)
Adds a unified API for key derivation functions like PBKDF2, HKDF, Argon2, and Scrypt.
Why it's important:
- Critical for post-quantum cryptography and hybrid encryption
- Standardizes password-based key generation
- Reduces security mistakes in custom key derivation implementations
Expected usage:
// Conceptual API
KeyDerivationFunction kdf = KeyDerivationFunction.getInstance("Argon2");
SecretKey derivedKey = kdf.deriveKey(password, salt, keyLength);
Platform Changes
Removal of the 32-bit x86 Port (JEP 503)
Java 25 removes support for 32-bit x86 architecture on both Windows and Linux.
Rationale:
- 32-bit servers and PCs are virtually extinct for Java deployments
- Frees development resources for modern platform features
- Simplifies code paths and reduces maintenance overhead
Impact:
Minimal for most developers, as 64-bit has been the standard for years. Allows the JDK to progress faster without legacy constraints.
Getting Started with Java 25
Installation and Setup
Java 25 is available from multiple vendors:
- Oracle JDK (commercial support)
- OpenJDK builds (open source)
- Vendor distributions (Eclipse Temurin, Amazon Corretto, etc.)
Migration Considerations
As an LTS release, Java 25 provides:
- Long-term support and updates
- Stability for enterprise adoption
- Backward compatibility with existing applications
Preview Features
To experiment with preview features, use:
javac --enable-preview --release 25 YourClass.java
java --enable-preview YourClass
Conclusion
Java 25 represents a significant milestone in Java's evolution, consolidating innovations from projects Loom, Amber, Panama, and Leyden into a stable, enterprise-ready platform. The release demonstrates Java's commitment to:
- Developer productivity through reduced boilerplate and improved syntax
- Performance via better startup times, memory efficiency, and JIT optimizations
- Modern computing with enhanced concurrency models and AI-ready features
- Security through updated cryptographic APIs and post-quantum preparation
As Java enters its fourth decade, this LTS release provides a solid foundation for the next generation of applications while maintaining the reliability and compatibility Java is known for.
Whether you're building microservices, AI applications, or enterprise systems, Java 25 offers compelling improvements that can enhance your development experience and application performance.
Sources and Further Reading
This comprehensive guide is based on official documentation and expert analysis from multiple sources:
Official Documentation:
- Oracle Releases Java 25 - Official press announcement with overview of new JEPs
- OpenJDK JDK 25 Project - Complete list of JEPs and their status in Java 25
- Oracle Java 25 Language Documentation - Language and VM specifications
Individual JEP Specifications:
- JEP 506: Scoped Values
- JEP 521: Generational Shenandoah
- JEP 470: PEM Encodings of Cryptographic Objects (Preview)
- JEP 503: Remove the 32-bit x86 Port
Expert Analysis and Reviews:
- InfoWorld: "JDK 25: The new features in Java 25" by P. Krill - In-depth analysis of Java 25 features and their significance
- JetBrains: "Java 25 LTS and IntelliJ IDEA" - Developer-focused highlights including compact object headers and Shenandoah GC improvements
- HappyCoders.eu: "Java 25 Features (with Examples)" - Detailed examples of Scoped Values, Stable Values, module imports, and more
- Foojay.io: "Here's Java 25, Ready to Perform to the Limit" - Performance-focused analysis of the new release
Java 25 is now available for download. As an LTS release, it will receive updates and support for many years, making it an ideal target for migration and new projects.
Top comments (0)