Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

83 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Java 27

Table of Contents

Java 27, the next STS release that’s part of the six-month release cadence, will be released on the 15 September 2026, and once again, it helps move the language forward.

Note
Teaser of enhancements

Java 27 gathers nine JEPs across different areas that will enhance performance, memory efficiency, security, and concurrent programming, all while continuing to advance major language features.

With the default adoption of the G1 garbage collector across all environments, compact object headers reducing heap size, and post-quantum cryptography support for TLS 1.3, this release improves our application performance and security.

Meanwhile, structured concurrency reaches its seventh preview, providing developers with more reliable patterns for managing concurrent tasks, while new capabilities in pattern matching, lazy constants, and cryptographic object encoding continue to mature through their respective preview cycles.

To try out Java 27:

  1. Install it, either by:

    1. Downloading it from jdk.java.net/27, or

    2. Using a package manager:

      1. SDKman: sdk install java 27-open

      2. Homebrew (macOS): brew install openjdk@27

      3. Chocolatey (Windows): choco install openjdk27

  2. For preview features (JEP-531, JEP-532, JEP-533, JEP-538), compile and run with --enable-preview:

javac --enable-preview --release 27 YourFile.java
java --enable-preview YourFile
Important
Preview features may be withdrawn or changed in future releases

Preview APIs and language features are fully specified and implemented, but not permanent. Class files compiled with --enable-preview are marked with the JDK version that produced them, and the JVM refuses to load them on any other release. In practice this means we must recompile against every new JDK, and we should never ship preview-enabled artefacts to production or publish them to a shared artefact repository.

Note also that --release 27 is mandatory when using --enable-preview with javac, and that preview APIs are flagged with @PreviewFeature, so our build will emit warnings on every usage.

  1. The Vector API (JEP-537) is an incubator module rather than a preview feature, so it needs a different flag: the module has to be added explicitly at both compile and run time, and --enable-preview does nothing for it.

javac --add-modules jdk.incubator.vector YourFile.java
java --add-modules jdk.incubator.vector YourFile
Note
Preview vs. incubator

The two mechanisms are easy to confuse:

  • Preview features are located in the standard modules (java.base and friends), are enabled with --enable-preview, and are expected to be finalised largely as-is.

  • Incubator modules can be found under the jdk.incubator.* namespace, are enabled with --add-modules, may change substantially, or be dropped entirely, before standardisation.

Using an incubator module also produces a warning at both compile and run time, and incubator modules are not resolved by default even when they are present in the JDK image.

  • Performance gains with no effort required: The G1 garbage collector is now the default across all platforms, including resource-constrained environments. After years of refinement, (particularly the throughput work in Java 26), G1 performs comparably to the Serial GC on smaller machines whilst delivering superior latency characteristics. Compact Object Headers are enabled by default, which, during the development team’s testing, reduced heap consumption by 10 to 20 per cent and may improve throughput by 5 to 10 per cent in applications handling many short-lived objects. All these benefits, without us having to change a single line of code!

  • Security improvements that work automatically: Java Flight Recorder now automatically hides sensitive data that was captured in environment variables, system properties, and command-line arguments. This detection is based upon pattern-based filtering (for instance, anything matching password, token, or api*key). This prevents inadvertent leakage of credentials and access tokens in production recordings. Furthermore, TLS 1.3 connections now employ post-quantum hybrid key exchange algorithms that offer protection against potential future attacks where adversaries record encrypted traffic today for decryption once quantum computers become available. The platform selects X25519MLKEM768 by default when supported by the server, requiring no configuration adjustments.

  • Maturing preview features to experiment with: Several APIs continue advancing through their preview cycles whilst progressing towards finalisation. Structured Concurrency (now in its seventh preview) provides proven patterns for managing concurrent work that eliminate common pitfalls such as thread leaks and delayed cancellation. Pattern matching for primitives (fifth preview iteration) enables more natural type checking logic. The Vector API (twelfth incubator release) offers access to CPU-level vector operations for computation-intensive workloads. If we choose to adopt these features, feedback submitted via the OpenJDK mailing lists directly influences their final design.

  • Streamlined cryptographic operations: Handling PEM-encoded keys, certificates, and CRL data has been streamlined through the new API, rather than the more cumbersome approach we previously had to use. The implementation supports the standard encodings such as PKCS#8 and X.509, with straightforward handling of encrypted private keys. This addresses pain points identified in community surveys regarding interoperability with OpenSSL and similar tools.

  • Practical lazy initialisation support: The Lazy Constants API offers a clean way to defer expensive object creation until actually needed, with new Lazy Sets for implementing feature toggles and conditional logic without concurrency headaches. When a lazy value is initialised, the JVM marks it with the @Stable annotation internally, allowing constant folding optimisations to apply. We avoid the verbosity of double-checked locking or the initialisation-on-demand holder idiom whilst maintaining thread safety.

  • Maintaining a healthy platform: Outdated experimental APIs and long-deprecated options have been removed (including JVMCI, and VM options such as -noverify, -Xverify:none, and -noclassgc). This pruning keeps the codebase maintainable and reduces complexity for the OpenJDK team.

JEP Title Status

523

Make G1 the Default Garbage Collector in All Environments

Final

527

Post-Quantum Hybrid Key Exchange for TLS 1.3

Final

531

Lazy constants

Third preview

532

Primitive Types in Patterns, instanceof, and switch

Fifth preview

533

Structured Concurrency

Seventh preview

534

Compact Object Headers by Default

Final

536

JFR In-Process Data Redaction

Final

537

Vector API

Twelfth incubator

538

PEM Encodings of Cryptographic Objects

Third preview

This JEP, previously known as JEP-526: Lazy constants (Second preview) in Java 26, and as JEP-502: Stable Values in Java 25 introduces immutable value holders that are at most initialised once, as it will help us move towards deferred immutability through LazyConstant and StableSupplier.

One of the key benefits of lazy constants is in how they’re handled by the JVM. Internally, the lazy constants use the internal @Stable annotation, which, despite the values being non-final, marks them as not changing after the initial updates. Thanks to this, these values benefit from the same constant-folding optimisations as final fields.

Compared to the previous iteration, we see two changes:

  • Removal of low-level methods: The isInitialized and orElse methods have been removed to ensure the API’s usage remains strictly aligned with its primary design objectives.

  • Introduction of Set.ofLazy(…​): This new factory method has been added to facilitate the creation of a stable Set from a predefined collection of element candidates. This addition completes the suite of lazy-initialisation options, ensuring that List, Set, and Map all possess corresponding lazy versions.

For example, let’s defer both a single expensive value and the elements of a collection:

// We defer the initialisation, it'll be initialised at most once and is immutable.
// This enables constant-folding.
private final LazyConstant<Integer> meaningOfLife = LazyConstant.of(() -> 42);
private final List<BigDecimal> numbers = List.ofLazy(42, BigDecimal::valueOf);

Integer getMeaningOfLife() {
    // The constant is computed on the first get() invocation.
    return meaningOfLife.get();
}

BigDecimal getNumber(int index) {
    // Each element is computed on its first access, independently of the others.
    return numbers.get(index);
}

List.ofLazy(…​) takes the size of the list and a mapper that produces the element for a given index, whereas Set.ofLazy(…​) takes a collection of candidate elements. Both defer the actual computation until the moment an element is first accessed, and both compute each element at most once.

This proposal aims to address some of the frequently encountered challenges in concurrent programming by introducing an API that treats groups of related tasks running in different threads as a single unit of work.

The proposed approach, also known as structured concurrency, will help us streamline error handling, cancellation, and observability, making concurrent code more reliable and easier to manage.

The main target is promoting a style of concurrent programming that eliminates common risks such as thread leaks and cancellation delays, while also improving the observability of concurrent code. The API itself is centred around StructuredTaskScope, which allows us to define a clear hierarchy of tasks and subtasks, ensuring that all subtasks are completed or cancelled before the parent task exits. This enforces a structured flow of execution, similar to single-threaded code, where subtasks are confined to the lexical scope of their parent task. The API also provides built-in shutdown policies (e.g., awaitAllSuccessfulOrThrow and anySuccessfulOrThrow) to handle common concurrency patterns, such as cancelling all subtasks if one fails or succeeds. We can also define our own shutdown policies.

By reifying the task-subtask relationship at runtime, structured concurrency makes it easier for us to reason about and debug concurrent programs. It also integrates well with observability tools, such as thread dumps, which can now display the hierarchical structure of tasks and subtasks.

This enhancement does not aim to replace existing concurrency constructs like ExecutorService or Future, but rather to complement them by offering a more structured and reliable alternative for managing concurrent tasks.

Compared to the sixth preview (JEP-525), the following changes have been made.

  • Introduction of the R_X Type Parameter: Both the StructuredTaskScope and Joiner interfaces now incorporate a third type parameter, R_X. This identifies the specific exception type that may be thrown by the StructuredTaskScope.join() method.

  • New open Method in StructuredTaskScope: A static open method is now available to implement the default join policy. It employs a UnaryOperator to determine the configuration for the StructuredTaskScope.

  • Updated Joiner Factory Methods: The allSuccessfulOrThrow(), anySuccessfulOrThrow(), and awaitAllSuccessfulOrThrow() methods have been modified to create joiners that trigger an ExecutionException during join() if the outcome is unsuccessful. Furthermore, new overloads have been introduced, allowing the use of a Function to define custom exception types.

  • Removal of awaitAll(): The Joiner.awaitAll() factory method has been officially removed from the API.

  • Replacement of onTimeout(): The onTimeout() method has been superseded by the timeout() method. This new method either yields the result or throws an exception upon a timeout-driven cancellation. Should an exception be thrown by timeout(), it will feature a CancelledByTimeoutException as its cause.

In this example, we’re starting three subtasks in parallel with the StructuredTaskScope API and waiting until we get the results of all the subtasks to compose the response. If one of the subtasks were to fail, the other, still-running subtasks will be cancelled, and scope.join() will throw the exception that happened in the failed subtask.

try (final var scope = StructuredTaskScope.open()) {
    Supplier<Person> personTask =
            scope.fork(() -> findPerson(userId));
    Supplier<Weather> weatherTask =
            scope.fork(this::fetchWeather);
    Supplier<Activity> activityTask =
            scope.fork(() -> findActivity(userId));

    scope.join();

    final var person = personTask.get();
    final var weather = weatherTask.get();
    final var activity = activityTask.get();

    return new GarderobeSelectionInput(person, weather, activity);
}

This code is quite a bit more robust and easier to read than in the "classic" unstructured concurrency style with an ExecutorService.

The StructuredTaskScope API makes it clear that the three subtasks are related and should be treated as a single unit of work. It also provides a clear mechanism for handling failures and cancellations, which can be tricky to manage in unstructured concurrency.

In the "traditional" approach, where we use an ExecutorService we will need to provide quite a bit of boilerplate code. If fetchWeather throws an exception, the remaining tasks keep consuming resources in the background unless we manually catch the exception and cancel each outstanding Future.

With StructuredTaskScope, the moment fetchWeather fails, the scope automatically triggers cancellation for findPerson and findActivity, unwinding cleanly and preventing background resource leaks without requiring any cleanup logic.

The twelfth iteration of an API for vector computations, this time without any significant changes compared to the previous iteration (JEP-529).

The Vector API gives us a portable way to express numerical algorithms in Java that explicitly leverage SIMD (Single Instruction, Multiple Data) CPU capabilities. Rather than relying on the HotSpot JIT compiler’s often hit-or-miss auto-vectorisation, it allows us to write code that predictably compiles into optimal vector instructions, such as x64 AVX or ARM NEON. This benefits compute-intensive tasks like machine learning, image processing, and cryptography, and falls back to standard scalar execution on hardware without native vector support.

The architects have confirmed that the API will remain in incubation until project Valhalla enters preview itself, so that the API can leverage the expected performance and in-memory representation enhancements. Valhalla is not part of JDK 27, but early-access builds are available for experimentation.

The Hotspot JVM will now always select the Garbage-First (G1) garbage collector, even on devices with only one CPU or less than 1792 MiB of RAM. If we were previously using the Serial collector, there might be a minor performance hit, but as always, when changing our GC we will need to measure the impact for our specific use case.

In case we do run into issues, the serial GC can be re-enabled through -XX:+UseSerialGC.

On 64-bit architectures, compact object headers will be made the default in the HotSpot JVM. This will shrink object headers from 96 bits down to 64 bits, thus reducing heap size, improving deployment density, and increasing data locality.

The heap consumption will be reduced by roughly 10-20 per cent, and the throughput increased by 5-10 per cent thanks to this change when upgrading to Java 27. The results vary based on how many small objects our applications have.

There have been several experiments to showcase the benefits of enabling compact object headers, and the results are promising. The following are some of the experiments that have been conducted:

In case we would prefer not to use the compact object headers yet, we can use -XX:-UseCompactObjectHeaders. But we do need to keep in mind that this option will be removed in a future release.

Every in-memory Java object has two parts: the object headers, and the actual payload data. Given the former’s changing, let’s look a bit closer at it.

The object header consists of two parts:

  • Mark word consisting of:

    • 25 unused bits

    • 31-bit identity hashcode

    • 1 unused bit, which was used in the past by the Concurrent Mark Sweep GC which was removed in Java 14

    • 4-bit age (used by the Garbage Collector to determine when to move an object from the young to the old generation)

    • 1 unused bit, which was used by biased locking, which was removed in Java 15

    • lock (used for synchronised locking, for example)

  • class word that contains the 32-bit offset to the class metadata in the Compressed Class space, so the Java Virtual Machine knows which class an object belongs to.

Mark Word (64 bits) Class Word (32 bits)

Unused

Identity Hash Code

Unused

Age

Unused

Lock bits

Compressed Class Pointer

25 bits

31 bits

1 bit

4 bits

1 bit

2 bits

32 bits

Here, the Mark and Class words have been merged into a 64-bit value.

Now the 27 unused bits are used as follows:

  • 4 reserved bits for Value classes

  • 1 self-forwarded tag bit

  • 22 bits for a compressed class pointer

Compact Object Header (64 bits)

Compressed Class Pointer

Identity Hash Code

Reserved

Age

Self-forwarded tag

Tag bits

22 bits

31 bits

4 bits

4 bits

1 bit

2 bits

Note

The Self-forwarded Tag is a bit set when a garbage collection copy operation fails, allowing a compact object header to mark the object as remaining in place without overwriting its essential class pointer with a self-referential pointer.

The JDK Flight Recorder will now redact command-line arguments and the initial values of environment variables and system properties in recordings, so as not to leak sensitive information.

If we need to adjust or fine-tune what gets masked, we can configure JFR’s redaction behaviour using sub-options on -XX:FlightRecorderOptions:

  • redact-key: Specifies filters for key-value pairs across environment variables and system properties.

  • redact-argument: Specifies filters for command-line arguments.

Filters rely on standard glob patterns, where * and ? serve as wildcards. Whenever a filter matches a key or argument, its value is replaced with [REDACTED] in the recording.

Multiple filters can be separated by semicolons and are evaluated in order, while multiple sub-options within -XX:FlightRecorderOptions are separated by commas.

Note
Troubleshooting redaction filters

If we need to troubleshoot or verify how our redact-argument and/or redact-key filters are matching, we can launch the JVM with -Xlog:jfr+redact=debug. This outputs detailed logging that reveals precisely which command-line arguments, environment variables, and system properties are being redacted.

So if we wanted to mask nationaldebt, we could do it like this:

java -XX:FlightRecorderOptions:'redact-key=*debt*' \
-XX:StartFlightRecording:filename=dump.jfr \
-Dnationaldebt=42 \
-jar application.jar

And verify it in this manner:

$ jfr print \
      --events InitialSystemProperty,InitialEnvironmentVariable \
      dump.jfr
[...]
jdk.InitialSystemProperty {
  startTime = 17:39:02.244 (2026-02-15)
  key = "nationaldebt"
  value = "[REDACTED]"
}

This JEP, first introduced as JEP-455, aims to enhance pattern matching by allowing primitives in all pattern contexts and allowing one to use them with instanceof and switch as well.

if (someObject instanceof int someInt) {
    System.out.println("The int was: " + someInt);
}

There are no changes between the fourth and fifth iteration JEP-530; some more feedback is just desired.

This enhances the security of our applications by implementing hybrid key exchange algorithms for TLS 1.3. These algorithms help safeguard our applications against future quantum computing attacks by leveraging both traditional and quantum-resistant algorithms. If our application uses the javax.net.ssl APIs, then we will get these benefits by default, without needing to change our code.

To achieve this, the JDK’s TLS 1.3 implementation will be enhanced with support for three new post-quantum hybrid key exchange schemes that combine ML-KEM with the traditional Ephemeral Elliptic-Curve Diffie-Hellman (ECDHE) algorithms:

  • X25519MLKEM768: Hybrid scheme combining ECDHE with X25519 and ML-KEM-768

  • SecP256r1MLKEM768: Hybrid scheme combining ECDHE using the secp256r1 curve with ML-KEM-768

  • SecP384r1MLKEM1024: Hybrid scheme combining ECDHE using the secp384r1 curve with ML-KEM-1024

These schemes are also referred to as named groups, so the names of these have been added to the Named groups section of the Java Security Standard Algorithm Names specification.

The JDK’s TLS 1.3 implementation will place the X25519MLKEM768 hybrid scheme at the front of the supported KEM list, thus making it the most preferred. This means we won’t have to make any changes to our code to leverage quantum-resistant TLS when available (given that we’re not specifying a different KEM programmatically).

The SSLParameters::setNamedGroups can be used to select a specific schema when configuring a TLS socket connection.

SSLSocket tlsSocket = (SSLSocket)(SSLContext.getDefault().
                                getSocketFactory().createSocket());
SSLParameters parameters = tlsSocket.getSSLParameters();

parameters.setNamedGroups(new String[] {
    "SecP256r1MLKEM768"
});
tlsSocket.setSSLParameters(parameters);
Note

It is important to act now, as attackers are actively harvesting data in preparation for future quantum computing attacks. This is known as the harvest now, decrypt later attack.

This JEP, which was previously previewed in Java 26 through JEP-524, will allow us to encode/decode cryptographic objects (keys, certificates, CRLs) to/from the PEM (Privacy-Enhanced Mail) format, simplifying a previously manual and error-prone process.

The API centres on BinaryEncodable, PEMEncoder, and PEMDecoder classes, supporting standards like PKCS#8 and X.509, with built-in encryption for private keys.

The goals include ease of use and interoperability with tools like OpenSSL, thus addressing a gap highlighted by developer surveys.

The design avoids extending legacy APIs such as KeyFactory in favour of a dedicated, immutable, and thread-safe solution, though encrypted keys require password handling via withEncryption()/withDecryption().

It is possible that future iterations may expand support for non-standard PEM types via the PEM class.

Compared to the previous preview in Java 26 through JEP-524, we see some changes:

  • PEM has become a Class, rather than a Record. Furthermore, it now includes constructors that accept Base-64 encoded content in byte arrays for convenience purposes.

  • DEREncodable has been renamed to BinaryEncodable.

  • EncryptedPrivateKeyInfo now has getKeyPair methods to decrypt PKCS#8-encoded text containing a PublicKey.

  • Both the getKey and getKeyPair methods of EncryptedPrivateKeyInfo that took a password and Provider now only take a Key.

  • The withFactory method of PEMDecoder has been renamed to withFactoriesOf to better indicate where the factories are obtained from.

  • CryptoException has been added to indicate failures in cryptographic processing at runtime.

There are some changes that may require us to update our code or configuration when migrating to Java 27 as some options have been removed or renamed. The following are the ones that I found most relevant.

The deprecated -XX:-UseCompressedClassPointers option no longer has any effect as this release removes uncompressed class pointers.

The -XX:InitiatingHeapOccupancyPercent option has been renamed to -XX:G1IHOP to make it clear that it is G1-specific. The old name will still be supported for now, but it’s recommended to update our configuration as soon as possible.

See also the removals under Other Changes, in particular the JVMCI removal.

Not all changes are part of a specific JDK Enhancement Proposal (JEP). If we want to find a full list, I recommend diving into the release notes. I’ve selected a small listing here of the ones that piqued my interest.

According to ISO-8601, the short zone offset format (e.g., +01) is valid, but it was not supported by Java’s date-time API.

This issue has been resolved, and now the short zone offset format is accepted when parsing date-time strings.

For example, the following code will now work without throwing an exception:

ISO_DATE_TIME.parse("2026-06-14T14:30:00+01")

The JNDI/LDAP service provider within the JDK’s java.naming module no longer assigns default values to the java.naming.factory.control, java.naming.factory.object, and java.naming.factory.state standard JNDI properties.

In previous JDK releases, the LDAP service provider automatically configured these properties with class names that weren’t part of the core JDK, which applications often supplied via their classpath. After this release, applications will no longer have access to these factories by default.

So if one of our applications relies on the LDAP service provider to pre-configure these three JNDI properties, we must now explicitly define these values within our own configuration, in accordance with the javax.naming.Context documentation.

The Javadoc tool now recursively copies subdirectories within doc-files directories to the generated output. Consequently, the -docfilessubdirs option, previously required to enable this behaviour, is no longer necessary and may be removed in a future release.

To restore the previous default behaviour, the -excludedocfilessubdir option now supports * as an argument, allowing all doc-files subdirectories to be excluded from copying.

This removes the property, which was deprecated in Java 25, thus reducing the complexity of the codebase.

The jcmd utility now supports Bash autocompletion like many other Linux tools. The script is located at conf/bash-completion/jcmd within the JDK installation directory and can be loaded directly into our shell or installed system-wide.

A new diagnostic command VM.security_properties has been added to retrieve all the enabled security properties. It is the security equivalent of VM.system_properties.

It’s used in the following manner: jcmd <pid> VM.security_properties.

The HashMap.putMapEntries() method has received fast paths for HashMap and Collections.unmodifiableMap(HashMap) resulting in performance gains between 66 and 86 per cent.

Broadly speaking, we can expect the following results:

  • 50% faster to add the contents of a HashMap

  • 40% faster to add the contents of an unmodifiable map

  • 80% faster to add the contents of a HashMap wrapped in a Collections.unmodifiableMap()

  • No detectable regression for other types

The detailed benchmark results can be found in the pull request that implemented this change.

The Arrays.binarySearch methods for primitive arrays have been optimised on x64 architectures using an AVX2 SIMD intrinsic. Instead of the standard scalar search that halves the search space per iteration, the intrinsic executes an 8-ary search using 7 parallel pivot comparisons, shrinking the search range by 8x per iteration.

Key highlights of this change include:

  • Average 1.5x speedup across primitive types for arrays exceeding per-type size thresholds

  • Up to 2.35x peak speedup observed for int arrays around 1,024 elements

  • Zero regression on small arrays: searches below thresholds (e.g., 256 elements for int, 768 for long) automatically fall back to standard C2-inlined scalar search

This optimisation is enabled by default on supported x64 hardware and can be disabled with the new diagnostic flag -XX:-UseAVX2BinarySearchIntrinsic.

The -noverify and -Xverify:none options were deprecated in Java 13, -noclassgc and -verifyremote in Java 24 and provided us with warnings if we still used them. The support for these is now being fully removed.

The experimental JVM Compiler Interface (JVMCI) has been removed in this release after more than a decade of experimentation. This includes all associated source code within the HotSpot JVM, the retirement of the jdk.internal.vm.ci, jdk.graal.compiler, and jdk.graal.compile.management modules, as well as the deletion of all JVMCI-related JIT-compilation policies. Additionally, all relevant configure feature flags and any command-line options containing the string JVMCI, such as -XX:+UseGraalJIT have been dropped.

The JVMCI was removed as the ongoing effort required to maintain and test this feature within the JDK outgrew the value it provided to the few projects utilising it. If we depend on it, we’ll need to carry and maintain it in our own downstream tree or use an older JDK release that still includes it.

This release once again brings something for everyone, making solid headway towards the long-term vision of Projects Valhalla, Panama, and Amber.

We gain immediate, code-free performance and memory efficiency out of the box through Compact Object Headers (JEP-534) and standardising G1 as the default garbage collector (JEP-523).

Security receives a timely boost with post-quantum TLS key exchanges (JEP-527) and automatic JFR data redaction (JEP-536).

Combined with steady refinements in Structured Concurrency (JEP-533) and Lazy Constants (JEP-531), Java continues to evolve predictably while keeping developer productivity firmly at the forefront.

Some useful resources to dive deeper into the Java ecosystem and stay up to date are:

  • GitHub repository - this article’s code

  • The release notes - The official source for all changes, including new features, bug fixes, and deprecations

  • OpenJDK Quality Group - A group of developers that helps ensure the quality of OpenJDK projects and FOSS in general through initiatives such as promoting the testing of projects on Early Access (EA) builds

  • The Java version almanack - A great resource with details on distributions, and API differences between various releases

  • Foojay - A magnificent Java community offering articles, tutorials, and discussions on the latest in the Java ecosystem

  • SDKman! - a great tool to manage the installation of various tools and languages

  • Inside Java - News updates by Java team members at Oracle

  • Java Community Process - the place where people can propose, discuss, and approve new features through a Java Specification Request (JSR)

© 2026 Simon Verhoeven. Licensed under the MIT License.
Last updated: August 2, 2026

About

An overview of the new features in Java 27.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages