Java 27, released on September 15, 2026, continues Java’s six-month release cadence as the second non-LTS release following Java 25. While Java 25 remains the current Long-Term Support (LTS) release, Java 27 brings meaningful improvements in memory efficiency, garbage collection, security, observability, and language expressiveness.
This release includes 9 JEPs: 4 finalized, 4 in preview, and 1 incubator. In this article, we will explore the new features of Java 27, with a particular focus on the finalized JEPs and their impact on Java development.
Note : Download OpenJDK 27 here: https://jdk.java.net/27/
JVM
JEP 523 : Make G1 the Default Garbage Collector in All Environments
G1 has been Java’s default garbage collector since Java 9, but not quite everywhere. Until Java 26, the HotSpot JVM automatically switched to the Serial GC when running in constrained environments with only one CPU or less than 1,792 MB of physical memory.
This behavior made sense when G1 was introduced as the default. Serial GC has a very simple implementation and historically provided better throughput and a smaller memory footprint on machines with limited resources.
However, G1 has evolved significantly since Java 9. Its native memory footprint has been reduced, and recent improvements have progressively closed the throughput gap with Serial GC. In Java 26, JEP 522 notably removed synchronization overhead from G1’s write barriers by introducing a second card table, providing significant throughput improvements.
With JEP 523, Java 27 completes this evolution: G1 is now the default garbage collector in every environment, regardless of the number of available CPUs or physical memory.
Serial GC is not being removed. Applications that benefit from its characteristics can still select it explicitly:
java -XX:+UseSerialGC -jar application.jar
Likewise, applications that already explicitly select G1, ZGC, Parallel GC, Shenandoah, or another available collector are unaffected.
JEP 534 : Compact Object Headers by Default
JEP 534 makes Compact Object Headers the default object-header layout in the 64-bit HotSpot JVM.
Compact Object Headers are part of Project Lilliput, whose goal is to reduce the memory footprint of Java objects by shrinking their headers from 96 bits down to 64 bits on 64-bit architectures.
I already wrote a dedicated deep-dive article on Project Lilliput, Java object memory layout, and JEP 519, where I explain in detail how Java objects are represented in memory, how object headers work, and how Compact Object Headers can significantly reduce memory consumption.
Before Java 27, Compact Object Headers had to be explicitly enabled:
java -XX:+UseCompactObjectHeaders -jar application.jar
From Java 27, nothing is required:
java -jar application.jar
The JVM automatically uses the compact layout. Applications that need to fall back to the legacy object-header layout can still disable the feature explicitly:
java -XX:-UseCompactObjectHeaders -jar application.jar
JEP 536 : JFR In-Process Data Redaction
JDK Flight Recorder (JFR) is one of the most useful tools available for diagnosing Java applications in production. It records information about CPU usage, garbage collection, threads, allocations, locks, I/O, and many other JVM events with relatively low overhead.
However, a JFR recording can also contain information about how the JVM was started and configured, including command-line arguments, environment variables, and system properties.
This can become a security problem because these values may contain sensitive information such as passwords, API keys, access tokens, or credentials.
For example, imagine starting an application like this:
$ export ACCESS_TOKEN=SECRET_TOKEN
$ java -XX:StartFlightRecording:filename=dump.jfr \
-Xmx2G \
-Djavax.net.ssl.keyStorePassword=SECRET_PASSWORD \
-jar application.jar \
--dbpassword ANOTHER_SECRET_PASSWORD
Before Java 27, those sensitive values could appear directly inside the JFR recording through events such as jdk.InitialEnvironmentVariable, jdk.InitialSystemProperty, and jdk.JVMInformation.
This becomes particularly problematic when .jfr files are shared with other developers, attached to support tickets, or uploaded to external systems for analysis.
JEP 536 addresses this problem by introducing in-process data redaction.
Instead of writing sensitive information into the recording and sanitizing the file afterward, JFR now identifies and redacts sensitive values before they are written to the recording.
Java 27 introduces two new sub-options to -XX:FlightRecorderOptions:
redact-key redact-argument
redact-key is used to identify sensitive environment variables and system properties, while redact-argument applies to command-line arguments.
JFR comes with default redaction filters for both command-line arguments and key-value pairs such as environment variables and system properties.
If neither redact-key nor redact-argument is specified, these built-in filters are automatically used. They cover common sensitive terms such as passwords, secrets, tokens, credentials, private keys, API keys, and client secrets.
Language
JEP 532 : Primitive Types in Patterns, instanceof, and switch (Fifth Preview)
JEP 532 continues the work of extending Java pattern matching to primitive types.
Until now, pattern matching has mainly been associated with reference types. This feature allows primitive types to participate in pattern matching as well.
For example:
int value = 100;
if (value instanceof byte b) {
System.out.println("Fits in a byte: " + b);
}
The pattern matches only if the conversion is exact, meaning that no information is lost. For example, 100 matches byte, while 1000 does not.
The feature also extends switch to support all primitive types, including long, float, double, and boolean:
long value = 42L;
String result = switch (value) {
case 0L -> "zero";
case 42L -> "the answer";
default -> "other";
};
Primitive patterns can also be used directly in case labels:
Object value = 42;
switch (value) {
case byte b -> System.out.println("byte: " + b);
case int i -> System.out.println("int: " + i);
default -> System.out.println("other");
}
JEP 532 is the fifth preview of this feature, after JEP 455, 488, 507, and 530.
Java 27 introduces no language changes compared to Java 26; the feature remains in preview to gather additional feedback before finalization.
API
JEP 527 : Post-Quantum Hybrid Key Exchange for TLS 1.3
JEP 527 strengthens TLS 1.3 against future quantum-computing attacks by introducing hybrid key exchange algorithms.
The idea is to combine a traditional elliptic-curve algorithm with the post-quantum ML-KEM algorithm. This protects against the “harvest now, decrypt later” threat, where encrypted traffic is captured today and potentially decrypted in the future using quantum computers.
Java 27 introduces three hybrid schemes: X25519MLKEM768, SecP256r1MLKEM768, and SecP384r1MLKEM1024.
X25519MLKEM768, which combines X25519 + ML-KEM-768, is enabled by default. Applications using the standard javax.net.ssl APIs can therefore benefit from post-quantum protection without changing their code, provided they do not override the default TLS named groups.
The supported groups can still be customized using jdk.tls.namedGroups or SSLParameters#setNamedGroups.
JEP 527 therefore makes Java applications more post-quantum ready by default, while maintaining compatibility with existing TLS infrastructure.
JEP 531 : Lazy Constants (Third Preview)
Lazy Constants provide a simple way to initialize a value only when it is first needed, while still allowing the JVM to treat that value as a true constant and apply optimizations such as constant folding.
Example:
static final LazyConstantLOGGER = LazyConstant.of(Logger::create); Logger logger = LOGGER.get();
The supplier is evaluated at most once successfully, in a thread-safe way, when get() is first called.
Java 27 brings two main changes compared to the previous preview:
isInitialized()andorElse()are removed.- Lazy collections are extended with
Set.ofLazy(...), alongside the existing lazyListandMapsupport.
JEP 531 remains a preview API in Java 27.
JEP 533 : Structured Concurrency (Seventh Preview)
Structured Concurrency treats a group of related concurrent tasks as a single unit of work, simplifying cancellation, error handling, and observability.
Using StructuredTaskScope, subtasks are forked and joined within a well-defined scope:
try (var scope = StructuredTaskScope.open()) {
Subtask<String> user = scope.fork(() -> findUser());
Subtask<Integer> order = scope.fork(() -> fetchOrder());
scope.join(); // Waits for subtasks to finish
return new Response(user.get(), order.get());
}
Java 27 mainly refines exception handling. StructuredTaskScope and Joiner now carry the type of exception that join() can throw, making the contract explicit at compile time.
The standard joiners now cause join() to throw the familiar ExecutionException instead of the preview-specific FailedException. Joiner.awaitAll() has also been removed.
JEP 533 remains a preview API in Java 27.
JEP 537 : Vector API (Twelfth Incubator)
The Vector API allows developers to express SIMD computations directly in Java, enabling the JVM to compile them into optimized vector CPU instructions such as AVX or NEON.
For example:
var va = FloatVector.fromArray(SPECIES, a, 0); var vb = FloatVector.fromArray(SPECIES, b, 0); var result = va.mul(vb).add(va);
Instead of processing one value at a time, the CPU can process multiple values in parallel using vector registers.
JEP 537 is the twelfth incubation of the API and introduces no substantial implementation changes compared with recent releases.
The Vector API remains incubating while waiting for the necessary Project Valhalla features. Once those become available, the API is expected to move from Incubator to Preview.
JEP 538 : PEM Encodings of Cryptographic Objects (Third Preview)
JEP 538 provides a standard Java API to encode and decode cryptographic keys, certificates, and CRLs in PEM format, avoiding manual Base64 parsing and formatting.
The API is mainly built around PEMEncoder and PEMDecoder:
String pem = PEMEncoder.of().encodeToString(publicKey); PublicKey key = PEMDecoder.of().decode(pem, PublicKey.class);
Private keys can also be encrypted and decrypted directly through the API.
Compared with Java 26, the main changes are:
DEREncodableis renamed toBinaryEncodable.PEMis now a regular class instead of a record.EncryptedPrivateKeyInfogains support for retrieving aKeyPair.- A new
CryptoExceptionrepresents cryptographic-processing failures.
JEP 538 remains a preview API in Java 27.
Conclusion
Java 27 continues the steady evolution of the platform with a strong focus on performance, memory efficiency, security, and developer productivity.
This release makes several important improvements available by default, including Compact Object Headers, G1 as the default garbage collector in all environments, stronger post-quantum TLS security, and safer JFR recordings.
At the same time, features such as Structured Concurrency, Lazy Constants, primitive patterns, PEM APIs, and the Vector API continue to mature through preview and incubation.
Java 27 is not an LTS release, but it clearly shows where the platform is heading: a more efficient JVM, stronger security defaults, and a simpler programming model for modern Java applications.
Is Java 27 a Long-Term Support (LTS) release?
No, Java 27 is a standard feature release with 6 months of support. The current LTS release remains Java 25. Java 27 is ideal for testing performance improvements and new features before the next LTS release.
What is the main impact of Compact Object Headers (JEP 534)?
Compact Object Headers shrink object headers from 96 bits down to 64 bits on 64-bit JVM architectures. This reduces memory footprint by default without needing explicit JVM flags in Java 27.
Why is G1 GC now enabled in constrained environments (JEP 523)?
G1’s footprint and throughput have improved significantly through recent releases. Serial GC is no longer automatically triggered on single-CPU or low-memory systems, though it remains available via -XX:+UseSerialGC.
How does JFR In-Process Data Redaction work (JEP 536)?
JFR redacts sensitive parameters (like passwords, keys, and tokens) directly in memory before writing them to the .jfr recording, preventing accidental leaks when sharing diagnostic logs.
Do I need to update my code to use Post-Quantum TLS 1.3 (JEP 527)?
No. The hybrid key exchange algorithm X25519MLKEM768 is enabled by default for TLS 1.3 connections, offering quantum-resistant security out of the box for standard Java TLS applications.