[EN] Java 27: What's new?

Julian | Sep 26, 2026 min read

Hello everyone,

Six months have passed since the Java 26 article - and as announced, Java consistently adheres to the six-month rhythm. Java 27 was released on September 15, 2026, again not an LTS release (the next one will come with Java 29 in September 2027), but a release with a clear signature: less new syntax, but fundamental work on storage, security and diagnostics.

Java 27 comes with nine independent JEPs: four of them are final, four are in another preview round, and one remains in the incubator. What’s striking is how many of the final features don’t change your syntax, but still affect every application that runs on the JVM - from the garbage collector to the TLS connection.

Let’s look at what really matters.


The finalized features

G1 becomes the standard – without exception (JEP 523)

Since Java 9, G1 has been the standard garbage collector - with one exception: machines with only one CPU or less than 1,792 MB of RAM previously automatically received the simpler Serial GC. This exception no longer applies with Java 27. The reason is unspectacular but convincing: Thanks to continuous improvements - most recently the reduced synchronization from Java 26 (JEP 522) - G1 now almost achieves the throughput of Serial GC, even on weak hardware. This makes it worthwhile to choose a uniform solution for all environments.

If you want to stick with Serial GC for a good reason - for example in very small containers where every megabyte of GC overhead hurts you - you can still do so explicitly:

java -XX:+UseSerialGC -jar deine-anwendung.jar

Two smaller but noticeable adjustments to G1 are also included: The heap ratio defaults (-XX:MinHeapFreeRatio / -XX:MaxHeapFreeRatio) move from 40%/70% to 0%/100%, which reduces unnecessary shrinking of the heap. And -XX:InitiatingHeapOccupancyPercent is now shorter called -XX:G1IHOP.

Objects on Diet: Compact Object Headers (JEP 534)

Every Java object carries invisible baggage with it: the object header. Previously on 64-bit systems this was 96 bits (12 bytes) - 64 bit mark word for locking, hash code and GC information, plus 32 bit class word for the pointer to the class. With Java 27 this is over by default: the header shrinks to 64 bits (8 bytes) by packing identity hash code, object age, lock bits and a compressed class pointer closer together.

That sounds like micro-optimization, but it’s not exactly that. In applications with many small objects - and this is the rule in Java, not the exception - this is noticeable with around 10-20% less heap usage and 5-10% more throughput. No code change necessary, you get this automatically.

If you want to go back to the classic header for compatibility reasons (e.g. native tooling relying on the old header layout):

java -XX:-UseCompactObjectHeaders -jar deine-anwendung.jar

Pro Tip: The flag is already marked as deprecated and will disappear in a future version. If you’re currently using it, it’s a temporary solution, not a permanent way out - resolve the actual incompatibility rather than relying on the flag permanently.

Cleaner diagnostics: JFR automatically redacts sensitive data (JEP 536)

The JDK Flight Recorder (JFR) records, among other things, program arguments and environment variables - practical for troubleshooting, but dangerous if an API key or password accidentally ends up there. Java 27 puts an end to this: JFR automatically detects sensitive key patterns and replaces the values ​​within the process before they even enter the recording.

By default, patterns such as *password*, *secret*, *token*, *api*key* or *credential* are recognized and redacted case-insensitively:

# Zusätzliche Schlüssel redigieren
java -XX:FlightRecorderOptions:'redact-key=ACCESS_TOKEN;*keyStorePassword' -jar app.jar

# Eigene Liste aus Datei laden
java -XX:FlightRecorderOptions:'redact-key=@keys.txt' -jar app.jar

# Defaults erweitern statt ersetzen
java -XX:FlightRecorderOptions:'redact-key=+*confidential*' -jar app.jar

# Redaction komplett abschalten (nicht empfohlen)
java -XX:FlightRecorderOptions:'redact-key=none,redact-argument=none' -jar app.jar

In the recording, the value then appears as [REDACTED] instead of in plain text. For teams that pass JFR dumps from production on for analysis - to colleagues, in ticket systems, to external support partners - this is a tangible gain in security without you having to configure anything.


Deep Dive: Post-Quantum TLS becomes standard (JEP 527)

The most strategically relevant JEP in this release will probably affect you without you having to touch a single line of code. The background: Encrypted connections that are intercepted and stored today could be decrypted in a few years using a sufficiently powerful quantum computer. This attack pattern is called “Harvest now, decrypt later” – data is collected today, cracked in the future.

Java 27 addresses this with hybrid key exchange for TLS 1.3: The classic, elliptic curve-based ECDHE exchange is combined with the quantum-resistant ML-KEM. Both methods run in parallel, so an attacker would have to break both to compromise the connection.

The variant X25519MLKEM768 is active by default. Two more are available if your security profile requires other curves:

# Alternative Kombinationen aktivieren
java -Djdk.tls.namedGroups=SecP256r1MLKEM768 -jar deine-anwendung.jar
java -Djdk.tls.namedGroups=SecP384r1MLKEM1024 -jar deine-anwendung.jar

The real highlight: Any application that communicates with TLS 1.3 via the standard APIs from javax.net.ssl receives protection automatically - without any code changes, without a rebuild. This is not a preview feature to try out, but from Java 27 it is an active reality in every TLS 1.3 connection that your code establishes.

Pro tip: If your application runs behind restrictive firewalls, load balancers or TLS-terminating proxies that accurately parse the TLS handshake, test the connection specifically against Java 27. Hybrid key exchange methods noticeably increase the size of the ClientHello packet - older middleboxes that are designed for fixed packet sizes can have problems with this.


Which continues to mature as a preview

Lazy Constants (JEP 531, 3. Preview)

The API around delayed initialized but still final values ​​is being sharpened. The low-level methods isInitialized() and orElse() are removed, but the last missing collection variant, Set.ofLazy(), is added:

private final LazyConstant<Validator> validator =
    LazyConstant.of(this::createValidator);

// createValidator() läuft erst beim ersten get()
public boolean isValid(String input) {
    return validator.get().test(input);
}

// Auch für Sets: jedes Element wird erst bei Bedarf berechnet
private final Set<String> enabledFeatures =
    Set.ofLazy(candidateFeatures, this::isFeatureEnabled);

This means that lazy variants for List, Map and Set are now available - can be used consistently, no matter which collection you need for expensive, deferred initialization.

Primitive Types in Patterns, instanceof und switch (JEP 532, 5. Preview)

Submitted for preview again, unchanged from Java 26 - a sign that there is no longer an open API dispute here, but only the regular preview process. Pattern matching on primitive types works including switch with guard conditions:

int score = ermittleScore();
String bewertung = switch (score) {
    case int s when s >= 90 -> "sehr gut";
    case int s when s >= 75 -> "gut";
    default -> "ausbaufähig";
};

The compiler checks carefully whether a value fits into the respective target type losslessly - 0.25 fits into a float, 0.1 does not because the value cannot be represented exactly. This precision check is the core of the feature and remains unchanged from Java 26.

Structured Concurrency (JEP 533, 7. Preview)

Unlike the last two previews, Structured Concurrency brings noticeable API changes in this round - a sign that finalization is getting closer (targeted for Java 28). Anyone who has used the last previews should take a closer look:

  • FailedException is history, instead join() now throws ExecutionException - consistent with the behavior of Future.get()
  • Joiner gets a third type parameter for the exception type: Joiner<T, R, R_X>
  • Joiner.onTimeout() is now simply called timeout()
  • awaitAll() as a joiner variant has been removed
  • You can now open scopes via StructuredTaskScope.open(cfg -> cfg.withTimeout(...).withName(...))
try (var scope = StructuredTaskScope.open(
        Joiner.<GeoCoordinates>anySuccessfulOrThrow())) {
    scope.fork(() -> primaryGeocoder.lookup(address));
    scope.fork(() -> backupGeocoder.lookup(address));
    return scope.join(); // liefert das erste erfolgreiche Ergebnis, bricht den Rest ab
}

Two geocoding services, one result, clean abort of the slower candidate - exactly the pattern Structured Concurrency is intended for. The price of maturity: If you are already experimenting productively with an earlier preview, you can expect a migration effort.

PEM Encodings of Cryptographic Objects (JEP 538, 3. Preview)

The API for encrypting and decrypting cryptographic objects in PEM format (keys, certificates, revocation lists) remains stable in its basic use; a few class and method names have been streamlined compared to Java 26:

PrivateKey privateKey = PEMDecoder.of()
    .withDecryption(passphrase.toCharArray())
    .decode(encryptedPemText, PrivateKey.class);

String encoded = PEMEncoder.of()
    .withEncryption(passphrase.toCharArray())
    .encodeToString(privateKey);

No more resorting to third-party libraries just for PEM handling - for enterprise security setups in which certificate management is part of everyday life, this saves boilerplate and sources of errors.

Vector API (JEP 537, 12. Incubator)

Unchanged from Java 26 again in the incubator - the twelfth round. The Vector API compiles vector operations into optimal CPU instructions at runtime, noticeably accelerating data analytics, AI inference and scientific workloads compared to scalar operations:

static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;

void addiereVektoren(float[] a, float[] b, float[] c) {
    int upperBound = SPECIES.loopBound(a.length);
    for (int i = 0; i < upperBound; i += SPECIES.length()) {
        var va = FloatVector.fromArray(SPECIES, a, i);
        var vb = FloatVector.fromArray(SPECIES, b, i);
        va.add(vb).intoArray(c, i);
    }
}

The reason for the long incubator phase: The API is waiting for value classes from Project Valhalla, which are expected as a preview for Java 28. Only then can the Vector API be truly rounded without detours via object wrappers.


Pro Tips/Warnings

Test G1 on legacy environments: If you run applications on very small instances or in very limited containers that previously received implicit Serial GC, test your deployment specifically with Java 27. The change is invisible for most cases, but “most cases” is not a replacement for your own load test.

Structured Concurrency: Preview remains Preview: The API changes in JEP 533 show how much can still change between two preview rounds. Don’t build anything production-critical on top of a preview API that you’re not prepared to adapt for each release, even if finalization for Java 28 is on the horizon.

Test Post-Quantum TLS against your infrastructure: Before putting Java 27 into production, test TLS connections through proxies, load balancers, and firewalls. Larger handshake packets are a simple but easily overlooked compatibility pitfall.


Conclusion: foundation instead of fireworks

Like its predecessor, Java 27 is not a release of big announcements - the real substance lies beneath the surface. G1 as a unified default collector, more compact object headers, and automatically redacted JFR records are three improvements that affect every application without you having to touch any code. But the real lever is JEP 527: With post-quantum TLS as the standard behavior, Java is taking one of the first big steps, invisible to developers, towards a quantum-secure future.

The previews - especially the API conversion at Structured Concurrency - show that the finalization of this long-standing project is getting closer. This should be confirmed with Java 28 in March 2027, and there will probably be the first harbingers of Project Valhalla in the form of value classes. Until then, it’s worth taking a look at Java 27, especially if memory consumption or TLS protection are an issue for you.

This text was created with the help of AI.