Publication Date: 17 March 2026
The following sections are included in these Release Notes:
These notes describe important changes, enhancements, removed APIs and features, deprecated APIs and features, and other information about JDK 26. In some cases, the descriptions provide links to additional detailed information about an issue or a change. This page does not duplicate the descriptions provided by the Java SE 26 ( JSR 401) Platform Specification, which provides informative background for all specification changes and might also include the identification of removed or deprecated APIs and features not described here. The Java SE 26 ( JSR 401) specification provides links to:
Annex 1: The complete Java SE 26 API Specification.
Annex 2: An annotated API specification showing the exact differences between Java SE 25 and Java SE 26. Informative background for these changes may be found in the list of approved Change Specification Requests for this release.
Annex 3: Java SE 26 Editions of The Java Language Specification and The Java Virtual Machine Specification. The Java SE 26 Editions contain all corrections and clarifications made since the Java SE 25 Editions, as well as additions for new features.
You should be aware of the content in the Java SE 26 ( JSR 401) specification as well as the items described in this page.
The descriptions on this Release Notes page also identify potential compatibility issues that you might encounter when migrating to JDK 26. The Kinds of Compatibility page on the OpenJDK wiki identifies the following three types of potential compatibility issues for Java programs that might be used in these release notes:
Source: Source compatibility preserves the ability to compile existing source code without error.
Binary: Binary compatibility is defined in The Java Language Specification as preserving the ability to link existing class files without error.
Behavioral: Behavioral compatibility includes the semantics of the code that is executed at runtime.
See CSRs Approved for JDK 26 for the list of CSRs closed in JDK 26 and the Compatibility & Specification Review (CSR) page on the OpenJDK wiki for general information about compatibility.
The full version string for this release is build 26+35 (where "+" means "build"). The version number is 26.
IANA Data 2025b
JDK 26 contains IANA time zone data version 2025b. For more information, refer to Timezone Data Versions in Java Runtimes.
➜ Primitive Types in Patterns, instanceof, and switch (Fourth Preview)
Enhance pattern matching by allowing primitive types in all pattern contexts,
and extend instanceof and switch to work with all primitive types. This is a preview language feature.
➜ HTTP/3 for the HTTP Client API
Update the HTTP Client API to support the HTTP/3 protocol, so that libraries and applications can interact with HTTP/3 servers with minimal code change.
See JEP 517
➜ Lazy Constants (Second Preview)
Introduce an API for lazy constants, which are objects that hold unmodifiable data. Lazy constants are treated as true constants by the JVM, enabling the same performance optimizations that are enabled by declaring a field final. Compared to final fields, however, lazy constants offer greater flexibility as to the timing of their initialization. This is a preview API.
➜ Structured Concurrency (Sixth Preview)
Simplify concurrent programming by introducing an API for structured concurrency. Structured concurrency treats groups of related tasks running in different threads as single units of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. This is a preview API.
See JEP 525
➜ Vector API (Eleventh Incubator)
Introduce an API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPUs, thus achieving performance superior to equivalent scalar computations.
See JEP 529
➜ PEM Encodings of Cryptographic Objects (Second Preview)
Introduce an API for encoding objects that represent cryptographic keys, certificates, and certificate revocation lists into the widely-used Privacy-Enhanced Mail (PEM) transport format, and for decoding from that format back into objects. This is a preview API.
See JEP 524
➜ G1 GC: Improve Throughput by Reducing Synchronization
Increase application throughput when using the G1 garbage collector by reducing the amount of synchronization required between application threads and GC threads.
See JEP 522
➜ Ahead-of-Time Object Caching with Any GC
Enhance the ahead-of-time cache, which enables the HotSpot Java Virtual Machine to improve startup and warmup time, so that it can be used with any garbage collector, including the low-latency Z Garbage Collector (ZGC). Achieve this by making it possible to load cached Java objects sequentially into memory from a neutral, GC-agnostic format, rather than map them directly into memory in a GC-specific format.
See JEP 516
➜ Prepare to Make Final Mean Final
Issue warnings about uses of deep reflection to mutate final fields. These warnings aim to prepare developers for a future release that ensures integrity by default by restricting final field mutation, which will make Java programs safer and potentially faster. Application developers can avoid both current warnings and future restrictions by selectively enabling the ability to mutate final fields where essential.
See JEP 500
➜ Remove the Applet API
Remove the Applet API, which was deprecated for removal in JDK 17 (2021). It is obsolete because neither recent JDK releases nor current web browsers support applets.
See JEP 504
The following are some important changes in and information about this release. In some cases, additional details about the changes described below are provided in these Release Notes.
Prior to JDK 26, in the JDK default implementation of the HTTP server in the jdk.httpserver module, the HttpExchange attribute map was shared with the enclosing HttpContext.
Since JDK 26, by default, context attributes are no longer shared with all of their exchanges. Instead, each exchange has its own map of attributes. This default behavior can be reverted to the pre-JDK 26 behavior by setting the jdk.httpserver.attributes system property.
See the jdk.httpserver module-info for more information.
A virtual thread that tries to initialize a class already being initialized by another thread will now, in most cases, be unmounted from its carrier while waiting. Previously, the behavior was to pin the virtual thread to its carrier while waiting for the other thread to execute the class initializer.
This change may improve performance in some cases, as unmounting from the carrier releases a platform thread, allowing the JDK virtual thread scheduler to mount a different virtual thread.
The change also helps address the pathological case where all platform threads available to the JDK virtual thread scheduler are pinned by virtual threads waiting for another thread to execute a class initializer. If the thread executing the class initializer blocks or waits on something that requires a virtual thread to execute, the system could become deadlocked, as no virtual thread would be able to continue execution.
This section describes some of the enhancements in Java SE 26 and JDK 26. In some cases, the descriptions provide links to additional detailed information about an issue or a change. The APIs described here are provided with the Oracle JDK. It includes a complete implementation of the Java SE 26 Platform and additional Java APIs to support developing, debugging, and monitoring Java applications. Another source of information about important enhancements and new features in Java SE 26 and JDK 26 is the Java SE 26 ( JSR 401) Platform Specification, which documents the changes to the specification made between Java SE 25 and Java SE 26. This document includes descriptions of those new features and enhancements that are also changes to the specification. The descriptions also identify potential compatibility issues that you might encounter when migrating to JDK 26.
This release upgrades the Unicode version to 17.0, which includes updated versions of the Unicode Character Database and Unicode Standard Annexes #9, #15, and #29:
java.lang.Character class supports the Unicode Character Database, which adds 4,803 characters, for a total of 159,801 characters. The new additions include 4 new scripts:
java.text.Bidi and java.text.Normalizer classes support Unicode Standard Annexes, #9 and #15, respectively.java.util.regex package supports Extended Grapheme Clusters based on the Unicode Standard Annex #29.For more details about Unicode 17.0, refer to the Unicode Consortium’s release note.
Process has a new close() method and supports AutoCloseable. Closing a process ensures that it has terminated and its streams and underlying resources are released. When used with try-with-resources, the process and its streams are closed when the try-with-resources block exits.
See java.lang.Process for details and examples.
New default methods min() and max() are added to the java.util.Comparator interface, which allow finding greater or smaller of two objects, according to this Comparator without changing existing implementations of the comparator.
Setting the connection backlog to > 200 in java.net.ServerSocket, java.nio.channels.ServerSocketChannel, and java.nio.channels.AsynchronousServerSocketChannel is now effective on Windows. Previously it was clamped at 200.
Server applications that use a higher backlog value will now queue more incoming connections, at the operating system level, rather than rejecting the connection.
A new static ofFileChannel(FileChannel channel, long offset, long length) method has been added to java.net.HttpRequest.BodyPublishers. This method provides an HttpClient request body publisher to upload a certain region of a file. The new publisher does not modify the state of the passed FileChannel, streams the file channel bytes as it publishes (i.e., avoids reading the entire file into the memory), and can be leveraged to implement sliced uploads.
RMI will use TLS connections if the javax.rmi.ssl.SslRMIClientSocketFactory class is used. These connections now have TLS endpoint identification enabled by default. This may cause some previously-working TLS connections to fail. If this occurs, ensure that the certificate presented by the server has a Subject Alternative Name that matches the server's hostname. Alternatively, endpoint identification for RMI TLS connections can be disabled on the client side by setting the jdk.rmi.ssl.client.enableEndpointIdentification system property to false.
JDK 26 includes support for the JDBC 4.5 MR. That MR provides the following updates to the JDBC Specification:
SQLPermission for removalDECFLOAT and JSON to JDBCType.java and Types.javaArray, Blob, Clob, Nclob, and SQLXML interfaces to extend and support AutoClosable. This adds a default implementation of the close method which calls the free method.Statement interface in JDK 9 to the Connection interface
enquoteIdentifier will throw a SQLException if DatabaseMetaData::getIdentifierQuoteString does not return a double quoteisSimpleIdentifier will now return false if the String passed to the method is a SQL Standard reserved wordThis update may have an impact on compatibility with some JDBC driver implementations:
java.text.NumberFormat now supports lenient parsing of minus signs in negative patterns when NumberFormat.isStrict() returns false. This behavior is enabled by default and can be disabled with NumberFormat.setStrict(true). When lenient, the concrete implementations, DecimalFormat and CompactNumberFormat, use CLDR's parseLenient data to recognize alternate minus signs. For example, text using the MINUS SIGN (U+2212) as the negative prefix is now correctly parsed:
jshell> var num = NumberFormat.getNumberInstance().parse("\u22123")
num ==> -3
java.time.Instant has a new method to simplify adding a Duration to an Instant. The plusSaturating(Duration) method adds a Duration to an Instantusing saturating arithmetic. The method never overflows or exceeds the Instant range, and returns the nearest bound(Instant.MINorInstant.MAX`) instead of throwing an exception.
New constants are added to java.time.Duration for the minimum and maximum values. Duration.MIN is the smallest (negative) duration and Duration.MAX is the largest (positive) duration.
java.util.UUID.ofEpochMillis(long) has been added to create a type 7 UUID from a given Unix epoch timestamp.
A new method getTotalGcCpuTime() has been added to java.lang.management.MemoryMXBean, that returns a long result with the accumulated CPU time in nanoseconds for GC related activity.
Although added as a standard API, possible usage may be in conjunction with the ProcessCpuTime property defined by the JDK-specific management interface com.sun.management.OperatingSystemMXBean.
The G1 garbage collector now eagerly reclaims eligible humongous (very large objects that occupy more than half a heap region) objects containing references. Instead of requiring liveness analysis (concurrent marking) of the entire Java heap, G1 can collect these objects at any garbage collection pause if they are not referenced any more.
This mechanism applies to both humongous arrays of references (e.g. Object[]) and regular humongous objects.
This change allows for prompt recovery of memory previously held by such objects, particularly if they are short-lived. This improves garbage collection efficiency and reduces heap usage.
The G1 garbage collector now throws an OutOfMemoryException when the garbage collection overhead is more than GCTimeLimit percent (default value 98) and the free Java heap is less than GCHeapFreeLimit percent (default value 2) for five consecutive garbage collections.
This feature is enabled by default. It can be disabled using the -XX:-UseGCOverheadLimit option.
The implementation mirrors the functionality already provided by the Parallel garbage collector. However there may be differences in the exact conditions for the OOME triggers as G1 calculates garbage collection overhead and free Java heap slightly differently.
Enhance the ahead-of-time cache, which enables the HotSpot Java Virtual Machine to improve startup and warmup time, so that it can be used with any garbage collector, including the low-latency Z Garbage Collector (ZGC).
Prior to JEP 516: Ahead-of-Time Object Caching with Any GC, some of the AOT optimizations of the AOT cache from project Leyden, introduced in JDK 24 by JEP 483: Ahead-of-Time Class Loading & Linking, did not work when using ZGC. The state of objects could not be cached due to memory mapping the object state bit by bit from a file into the heap, which requires a common object format. The advanced memory layout of ZGC was incompatible with the simpler object format used by other GC implementations.
JEP 516 introduces a new way of loading objects in the background, instead of directly memory mapping a file, which is compatible across all GC implementations. Hence, the full range of optimizations of the AOT cache is now available across all GC implementations, including ZGC.
The thread dump generated by the com.sun.management.HotSpotDiagnosticMXBean.dumpThreads API, and the diagnostic command jcmd <pid> Thread.dump_to_file, now includes information about park blocker owner for threads that are parked on java.util.concurrent.locks.AbstractOwnableSynchronizer objects.
The keytool command reads passwords from the system console to prevent them from being displayed on the screen. However, the console is usually available only when both the standard input and output streams are not redirected. Previously, if the standard output stream was redirected into a file or another command, the console was unavailable and the input password was echoed on the screen. This enhancement improves password handling to ensure that the password is not displayed on the screen even if the standard output stream is redirected. This enhancement has also been made to the jarsigner command and the JAAS TextCallbackHandler API.
The <java-home>/lib/src.zip file distributed with the Oracle JDK now contains sources for JCE, JGSS, and JSSE. Debugging tools can now examine or display most of the security source files.
A new security property named jdk.crypto.disabledAlgorithms has been introduced to disable algorithms for JCE/JCA cryptographic services. Initially, this property only supports the Cipher, KeyStore, MessageDigest, and Signature services. This property is defined in the java.security file and initially no algorithms are disabled by default. However, this may change in the future. This security property can be overridden by a system property of the same name if applications need to re-enable algorithms.
See Disabled and Restricted Cryptographic Algorithms for more information.
The JDK now supports creating and verifying JAR files signed with the post-quantum ML-DSA algorithm, using PKCS #7 as defined in RFC 9882. This new feature is available through both the JarSigner API and the jarsigner tool.
A new Cipher algorithm named "HPKE" has been introduced. The HPKE algorithm is defined in RFC 9180: Hybrid Public Key Encryption and is a public key encryption scheme for encrypting arbitrary-sized plaintexts with a recipient's public key. HPKE combines a key encapsulation mechanism (KEM), a key derivation function (KDF), and an authenticated encryption with additional data (AEAD) cipher. All KEM, KDF, and AEAD algorithm identifiers defined in RFC 9180 are supported.
The new HPKEParameterSpec class allows users to choose algorithm identifiers and set other parameters such as HPKE modes, application-supplied info, and mode-specific keys. The API documentation provides a simple example showing how to set parameters and perform encryption and decryption.
See Securely Exchanging Messages with HPKE and the HPKEParameterSpec Class for more information.
The default "SunX509" KeyManagerFactory for TLS now supports the same algorithm constraints and certificate check functionality as the "PKIX" KeyManagerFactory. Selection and prioritization of the local certificates chosen by the KeyManager is based on the following checks:
signature_algorithms_cert TLS extension.jdk.tls.disabledAlgorithms and jdk.certpath.disabledAlgorithms security properties.The legacy behavior of the "SunX509" key manager, no checking of local certificates, can be restored by setting the jdk.tls.SunX509KeyManager.certChecking system property to false.
A new property called "jdk.xmldsig.SecureRandom" has been added to DOMSignContext so you can use your own SecureRandom instance. To use this property, call signContext.setProperty("jdk.xmldsig.SecureRandom", yourSecureRandom) before calling XMLSignature.sign(signContext).
The API documentation generated by JavaDoc now features a dark theme. The theme can be switched between the default light theme, the new dark theme, and the theme indicated by the system setting using the new theme button in the navigation bar.
This section describes the APIs, features, and options that were removed in Java SE 26 and JDK 26. The APIs described here are those that are provided with the Oracle JDK. It includes a complete implementation of the Java SE 26 Platform and additional Java APIs to support developing, debugging, and monitoring Java applications. Another source of information about important enhancements and new features in Java SE 26 and JDK 26 is the Java SE 26 ( JSR 401) Platform Specification, which documents changes to the specification made between Java SE 25 and Java SE 26. This document includes the identification of removed APIs and features not described here. The descriptions below might also identify potential compatibility issues that you could encounter when migrating to JDK 26. See CSRs Approved for JDK 26 for the list of CSRs closed in JDK 26.
Java Object Finalization will be removed from a future JDK version. In anticipation of this, use of this mechanism has been removed from the class javax.imageio.stream.ImageInputStreamImpl and from all its subclasses.
This should have no impact on almost all applications, since no JDK provided Image I/O code needed the finalization mechanism. Applications which use third party Image plugins may be affected in extremely specific cases where those plugins may fail to flush the stream and relied on finalization. However, that is further limited to applications which use FileCacheImageOutputStream or MemoryCacheImageOutputStream, since these are the only stream types that would need flushing. It should also be noted that if the application itself is relying on finalization to flush the stream, then it cannot know when it may safely close the stream and so very likely has a bug.
Another scenario is a third party ImageIO stream which acquires native resources. If the application is relying on finalization to release these, it may need to be updated to explicitly close the ImageIO stream. However, this is also a case in which, if the application is not doing this already, it is may be saving truncated streams.
The method java.lang.Thread.stop() has been removed in this release. This inherently unsafe method was deprecated in JDK 1.2 (1998), deprecated for removal in JDK 18, and was re-specified in JDK 20 to throw UnsupportedOperationException unconditionally. Code that uses this method will no longer compile. Code using this method that is compiled to older releases will throw NoSuchMethodError instead of UnsupportedOperationException if executed on JDK 26 or newer.
The JDK built-in support for InfiniBand Sockets Direct Protocol (SDP) on Linux has been removed. SDP has been obsolete for many years and is no longer supported by any mainstream distribution.
The system property com.sun.sdp.conf that could be used to configure SDP usage, and the sample configuration file $JAVA_HOME/conf/sdp/sdp.conf.template, are also removed.
The following terminally deprecated methods have been removed:
java.net.MulticastSocket methods:
public void setTTL(byte ttl) throws IOException
public byte getTTL() throws IOException
public void send(DatagramPacket p, byte ttl) throws IOException
java.net.DatagramSocketImpl methods:
protected void setTTL(byte ttl) throws IOException
protected byte getTTL() throws IOException
Normalization of file names is not performed by APFS, which succeeded HFS+ as the macOS file system as of September 2017. The system property jdk.nio.path.useNormalizationFormD was added in JDK 20 to allow enabling such normalization if it was needed for backward compatibility. Given that no currently supported version of macOS performs file path normalization, support for this property has been removed.
The deprecated XML interchange feature in javax.management.modelmbean.DescriptorSupport is removed, meaning the constructor DescriptorSupport(String inStr) and the method toXMLString() are removed. Also the class javax.management.modelmbean.XMLParseException is removed, for which it would have been an error for code outside the package to have used for its own purposes.
The experimental and unsupported jrunscript tool has been removed from the JDK.
The jdk.jsobject module has been removed - it is included with JavaFX 24 and later.
The following root certificates, which are deactivated and no longer in use, have been removed from the cacerts keystore:
+ alias name "affirmtrustcommercialca [jdk]"
Distinguished Name: CN=AffirmTrust Commercial, O=AffirmTrust, C=US
+ alias name "affirmtrustnetworkingca [jdk]"
Distinguished Name: CN=AffirmTrust Networking, O=AffirmTrust, C=US
+ alias name "affirmtrustpremiumca [jdk]"
Distinguished Name: CN=AffirmTrust Premium, O=AffirmTrust, C=US
+ alias name "affirmtrustpremiumeccca [jdk]"
Distinguished Name: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US
The following security algorithm implementation requirements in the Java Security Standard Algorithm Names specification and the API specifications have been removed as they are no longer recommended and should not be in wide usage anymore:
AlgorithmParameters: DESede
Cipher:
DESede/CBC/NoPadding
DESede/CBC/PKCS5Padding
DESede/ECB/NoPadding
DESede/ECB/PKCS5Padding
RSA/ECB/PKCS1Padding
KeyGenerator: DESede
SecretKeyFactory: DESede
The following PBES2 algorithms from RFC 8018: PKCS #5: Password-Based Cryptography Specification Version 2.1 have been added as new requirements:
AlgorithmParameters:
PBEWithHmacSHA256AndAES_128
PBEWithHmacSHA256AndAES_256
Cipher:
PBEWithHmacSHA256AndAES_128
PBEWithHmacSHA256AndAES_256
Mac:
PBEWithHmacSHA256
SecretKeyFactory:
PBEWithHmacSHA256AndAES_128
PBEWithHmacSHA256AndAES_256
PBKDF2WithHmacSHA256
The Oracle JDK will no longer accept 3rd Party cryptographic providers signed with certificates issued by the old (expired) Sun JCE CA root certificate.
The Sun JCE Certificate Authority issued code-signing certificates to customers so they can create third-party JCE cryptographic providers for use in the JDK (and the Sun/Oracle JDK-derived distributions). This Authority was taken over by Oracle, and in 2016 a newer, stronger root certificate was created to anchor newly issued certificates.
Provider jars signed using certificates issued by the old Sun JCE CA may encounter the following error:
java.lang.SecurityException: JCE cannot authenticate the provider MyProvider
...
Caused by: java.util.jar.JarException: MyProvider.jar is not signed by a trusted signer.
These older certificates can often be identified by the O=Sun Microsystems Inc field in the certificate used to sign the jar file:
% jarsigner -verify -verbose -certs MyProvider.jar
941 Tue Feb 05 18:15:34 PST 2013 META-INF/MANIFEST.MF
...deleted...
- Signed by "CN=Your Company, OU=Java Software Code Signing, O=Sun Microsystems Inc"
The older certificates issued by the Sun JCE CA expired in 2021 at the latest, and should be reissued using the new Oracle CA.
Additional sources of information about the APIs, features, and options deprecated in Java SE 26 and JDK 26 include:
You should be aware of the contents in those documents as well as the items described in this release notes page.
The descriptions of deprecated APIs might include references to the deprecation warnings of forRemoval=true and forRemoval=false. The forRemoval=true text indicates that a deprecated API might be removed from the next major release. The forRemoval=false text indicates that a deprecated API is not expected to be removed from the next major release but might be removed in some later release.
The descriptions below also identify potential compatibility issues that you might encounter when migrating to JDK 26. See CSRs Approved for JDK 26 for the list of CSRs closed in JDK 26.
The java.net.SocketPermission class has been deprecated for removal. This permission cannot be used for controlling access to resources as the Security Manager is no longer supported.
The method setPerformancePreferences in java.net.Socket, java.net.SocketImpl, and java.net.ServerSocket was introduced in Java 1.5 with the intention of providing a declarative API for configuring the performance-wise characteristics of the underlying socket, yet it has always been a no-op. These methods are deprecated for removal without any replacement.
The -Xmaxjitcodesize flag currently serves as an alias for -XX:ReservedCodeCacheSize, setting the reserved code cache size in bytes, that is the maximum size for the JIT-compiled code cache. It has been long overdue for deprecation, being obsoleted as far back as 2002 (JDK 1.4.0). To simplify JVM configuration and ease flag discovery for users, this redundant flag has now been marked as deprecated, with the intent to be removed in future releases.
Current users of -Xmaxjitcodesize should instead use -XX:ReservedCodeCacheSize.
AlwaysActAsServerClassMachine and NeverActAsServerClassMachine Flags
(JDK-8370843)
The AlwaysActAsServerClassMachine and NeverActAsServerClassMachine flags are used to influence two separate behaviors: 1) which GC is chosen by default, and 2) whether client emulation mode is selected. Both flags have been marked as deprecated with the intent to be obsoleted and removed in future releases.
Users who rely on a specific GC being chosen through the AlwaysActAsServerClassMachine and NeverActAsServerClassMachine flags should instead explicitly configure the GC they want, for example by using -XX:+UseSerialGC or -XX:+UseG1GC.
Client emulation mode was used to emulate a client build on platforms with reduced virtual address space, mainly Windows 32-bit (see JDK-8166002). With Windows 32-bit being deprecated in JDK 24 (see JEP 479), the incentive for maintaining the client emulation mode feature is gone, and thus also the method to influence whether it is enabled is no longer needed.
When the flags are obsoleted and removed, users will no longer be able to influence whether client emulation mode is enabled via the NeverActAsServerClassMachine flag.
The AggressiveHeap flag was originally introduced to optimize performance for specific benchmarking scenarios, but its lack of transparency and limited applicability have led to confusion and inconsistent results for general workloads. To simplify JVM configuration and encourage users to explicitly select tuning options that best fit their application needs, this flag has now been marked as deprecated with the intent to be removed in future releases.
Users who require their application to continue with similar behavior should specify the corresponding flags:
-XX:+UseParallelGC -XX:+UseLargePages -XX:-ResizeTLAB -XX:TLABSize=256K -XX:YoungPLABSize=256K -XX:OldPLABSize=8K -XX:ThresholdTolerance=100
and set the following values:
-Xmx and -Xms to half the available physical memory-XX:NewSize to 3/8 of available physical memory-XX:MaxNewSize to the value of -XX:NewSize
To simplify heap sizing and reduce user confusion, the MaxRAM flag has been marked as deprecated with the intent to be obsoleted and removed in future releases. Explicit configuration of MaxRAM is rarely necessary, as the JVM accurately detects available physical memory and system commit limits. Setting MaxRAM above the actual physical memory may lead to incorrect heap sizing and is not a common use case.
Additionally, the default value of MaxRAM has been removed. From now on and until the MaxRAM flag is obsoleted, heap sizing calculations are based on the available memory on the system rather than the default value of MaxRAM, unless MaxRAM is explicitly set by the user.
Users who need to control the heap size directly are encouraged to use flags such as -Xms and -Xmx instead.
The following notes describe previous known issues or limitations that have been corrected in this release.
During the setup of new connections, java.net.http.HttpClient now uses the signature schemes and named groups configured on SSLParameters when negotiating the TLS handshake. Previously these configured values were ignored.
The C2 JIT compiler can now compile Java methods with a large number of parameters. Previously, C2 would attempt to compile such methods but bail out, causing the JVM to fall back to C1-compiled code or the interpreter. This change enables applications to benefit from C2 optimizations for a wider range of methods, improving performance. No application changes are required to take advantage of this improvement.
G1, the default garbage collector, can again properly utilize Transparent Huge Pages (THP) on systems with the THP mode configured as madvise.
The issue preventing the option -XX:+UseTransparentHugePages from enabling THP has been resolved.
The JFR events jdk.ModuleExport, jdk.SymbolTableStatistics, and jdk.StringTableStatistics have been disabled in the default JFR configuration (default.jfc) to reduce overhead when JFR is not explicitly configured. To enable these events, set the corresponding event setting when starting a recording, for example:
-XX:StartFlightRecording:jdk.ModuleExport#enabled=true
Whenever a reference to an inner type of the kind A.B is found, javac needs to normalize the qualifier type A, so that any reference to potentially parameterized types are made explicit. This normalization occurs regardless of whether this type is explicitly provided in the source code, or inferred from the enclosing context. Some cases were found where no normalization was applied to the type qualifier -- e.g. if the qualifier is a type-variable type. The lack of normalization led to spurious errors, as the type reference was incorrectly classified as a raw type. This change adds the missing normalization step. While this change is generally beneficial, as spurious errors that would cause compilation to fail are no longer generated, there might be cases where the additional normalization steps might result in a change in overload resolution.
For example, assume the following snippet in which the result of the getter.get() method call is passed to an overloaded method with two candidates: m(T) and M(Object). Without the patch the following code prints Object, erroneously; with the patch the following code prints T, correctly. An erroneous classification of the qualified type means that the type G.Getter was treated as a raw type and the result of the method call was Object; the correct classification is to treat it as T <: Number and the return type of the method call to be Number. That very classification selects a different overload m before and after the patch:
static class Usage<T extends Number, G extends Getters<T>> {
public void test(G.Getter getter) {
m(getter.get()); // javac selects one of the overloads for m
}
void m(T t) { System.out.println("T"); }
void m(Object s) { System.out.println("Object"); }
}
static abstract class Getters<T> {
abstract class Getter {
abstract T get();
}
}
public static void main(String[] args) {
new Usage<Integer, Getters<Integer>>().test(new Getters<Integer>() {}.new Getter() { Integer get() { return 42; } });
}
The specification of java.lang.runtime.ObjectMethods.bootstrap method incorrectly claims its MethodHandles.Lookup argument is unused; it may cause an exception if the lookup does not have full privilege access.
Since JDK 18, it consistently throws a RuntimeException caused by StringConcatException if the lookup does not have full privilege access. The methodName is "toString", and all other arguments are valid. Beginning in JDK 26, it may throw an IllegalAccessException or return normally if the lookup does not have full privilege access, the methodName is "hashCode" or "equals", and all other arguments are valid.
The overwhelming majority of uses of ObjectMethods.bootstrap are through bootstrap methods. These provide a full-privilege lookup and are therefore not affected. This inconsistent behavior will be addressed by JDK-8378796 in JDK 27.
The following notes describe additional changes and information about this release. In some cases, the following descriptions provide links to additional detailed information about an issue or a change.
The behavior of java.io.PrintStream and java.io.PrintWriter has changed when writing to a custom output stream that throws InterruptedIOException. If the custom output stream's write method throws InterruptedIOException, then the PrintStream or PrintWriter is now marked in error so that checkError returns true. Historically, this exception caused the writing Thread's interrupted status to be set, without marking the stream in error.
In the class file format, the representable range of many integer values are narrower than that of the int primitive type in the Java programming language. Currently, the Class-File API truncates the most significant bytes of a user-provided int value upon writing to class file. Upon reading, the truncated value is zero or sign extended, depending on the type, back to an int, and may differ from the user-provided value. For instance, an int value 65536 would become 0 after this write-read to a u2 value .
To prevent such error-prone usage, the Class-File API now performs eager validation of int values that would be lost after a truncation, including the size of lists. Such unrepresentable data will result in an IllegalArgumentException. Users who used such silent truncation should migrate to explicit truncation before passing data instead.
Annotation access methods declared on java.lang.reflect.AnnotatedElement specify they throw NullPointerException if their argument is null. In prior releases, implementations of java.lang.reflect.AnnotatedType and its subinterfaces did not throw NullPointerException for isAnnotationPresent, getAnnotation, and getDeclaredAnnotation methods from AnnotatedElement. These methods now throw NullPointerException instead of returning false or null for a null argument.
The HTTP Client request timeout set using java.net.http.HttpRequest.Builder::timeout previously applied only until the response headers were received. Its scope has now been extended to also cover the consumption of the response body, if present.
java.net.HttpClient has been updated to stop sending the Content-Length header on HTTP/1.1 requests using a method other than POST or PUT when provided with a BodyPublisher that reports a contentLength() of zero bytes.
This behavior follows the recommendations in RFC 9110: HTTP Semantics.
Users who need the header may add it using the HttpRequest Builder. The header is restricted by default, and needs to be allowed by setting the system property jdk.httpclient.allowRestrictedHeaders to include content-length.
Previously, java.net.http.HttpRequest.BodyPublishers::ofFile(Path) could throw java.nio.file.NoSuchFileException when the provided Path was not associated with the default file system. This inconsistency has been removed by mapping these to java.io.FileNotFoundException, in line with the ofFile API specification.
java.net.HttpCookie has been updated to correctly handle cookies with both Expires and Max-Age attributes. RFC 6265 specifies that the Max-Age attribute should take precedence over the Expires attribute if both are present in the same cookie. This behavior change is reflected in the HttpCookie.getMaxAge method.
The JDK's implementation of the java.net.CookieStore interface has been updated to return an immutable java.util.List from the getURIs() and get(URI) methods. The updated implementation now matches the specification of these two methods.
java.nio.ByteOrder is converted from a class to an Enum to allow it to be used in expression switch and elsewhere the language can dispatch on an Enum, for example in switch. The ByteOrder enum is fully compatible with the class implementation. The BIG_ENDIAN, LITTLE_ENDIAN, and ByteOrder.nativeOrder() values remain a simple and effective way to test for the byte order.
Class java.text.DecimalFormat now uses the algorithm implemented in Double.toString(double) and in java.util.Formatter to format floating-point values.
As a consequence, in rare cases the outcome might be slightly different than with the old algorithm. For example, the double 7.3879E20 now produces "738790000000000000000" rather than "738790000000000100000" given appropriate formatting specifications.
To help migrating applications that might be impacted by this change, for a few releases the old algorithm will still be available to DecimalFormat and classes that depend on it, like NumberFormat. The old algorithm can be enabled with the "-Djdk.compat.DecimalFormat=true" option on the launcher command line. Absent this option, the new algorithm is used.
The locale data based on the Unicode Consortium's CLDR has been upgraded to version 48. Besides the usual addition of new locale data and translation changes, there are notable changes from the upstream CLDR, affecting Date/Time/Number formats:
CLDR-16439 zone alias South_Pole was moved to McMurdo, so remove it from Auckland (#4592)
CLDR-16665 key/type core values (#4577)
CLDR-13688 Correct the first day of week for Iceland from Monday to Sunday (#4379)
CLDR-18464 Add a Before Hijrah era to the Islamic calendars (#4581)
CLDR-18572 Add more European Englishes (#4645)
CLDR-18253 Add en_JP (#4634)
CLDR-18603 Add GyM, GyMEd availableFormats to root, en (#4679)
CLDR-18538 root,en: change H patterns without m[s] to add literal 'h' (#4708)
CLDR-9814 Recover Turkey metazone names (#4741)
CLDR-18788 Fix Russian metazones (#4833)
CLDR-13542 Fix Swiss grouping separator (#5019)
Note that locale data is subject to change in a future release of the CLDR. Although not all locale data changes affect the JDK, users should not assume stability across releases. For more details, please refer to the Unicode Consortium's CLDR release notes and their locale data deltas.
ThreadReference.popFrames() and ThreadReference.forceEarlyReturn() were previously documented as only throwing OpaqueFrameException for virtual threads. This indicated that the functionality cannot be performed on the virtual thread frame for a reason that is unique to virtual threads.
However, it was realized that there were error conditions that resulted in a NativeMethodException when in fact the underlying error was not due to a native method, and was not unique to virtual threads. The appropriate exception in this case would be an OpaqueFrameException instead of a NativeMethodException.
Both these APIs have now been updated to be consistent with when these two exceptions are thrown for both virtual threads and platform threads. This means you may now see these two APIs throw OpaqueFrameException for a platform thread when previously this was not possible.
StackFrame.SetValues, StackFrame.GetValues, StackFrame.PopFrames, and ThreadReference.ForceEarlyReturn all received specification updates to clarify when OPAQUE_FRAME and INVALID_SLOT errors are returned.
(1) The JDWP specification for StackFrame.GetValues did not mention OPAQUE_FRAME as a possible error, but it is possible. The specification has been updated to include language regarding when OPAQUE_FRAME can be returned.
(2) The JDWP specification for StackFrame.SetValue only mentioned OPAQUE_FRAME as a possible error for virtual threads, indicating that the operation is not possible on the specified frame. However, OPAQUE_FRAME is possible for other reasons, such as the frame being native. The specification has been updated to adopt the more general description of when OPAQUE_FRAME can be returned.
(3) The JDWP specification StackFrame.PopFrames and ThreadReference.ForceEarlyReturn was too specific with regards to when OPAQUE_FRAME can be returned. The specification has been updated to adopt the more general description of when OPAQUE_FRAME can be returned.
(4) The JDWP specification for StackFrame.SetValue failed to mention INVALID_SLOT as a possible error result. This has been fixed.
The class javax.management.remote.JMXServiceURL requires that a protocol is specified when using its String constructor, and will throw MalformedURLException if the protocol is missing. This behavior is now extended to the other constructors that take individual parameters, and the historical defaulting to the "jmxmp" protocol is removed.
The classes javax.management.AttributeList, and javax.management.relation.RoleList and RoleUnresolvedList, have historically accepted objects of the wrong type, and only verified types when (and after) the "asList()" method is called. This feature has been removed, and these classes never accept the wrong kind of Object. Most applications using these classes should not be affected.
The javax.management.MBeanServer method registerMBean now throws a RuntimeOperationsException instead of NullPointerException when invoked with a null "object" parameter. This correction aligns the implementation with the specification, and becomes the same as other methods in the class. This is not expected to affect most applications, and could only be noticed after other application errors have occurred.
If users do not specify the initial Java heap size using -Xms or -XX:InitialHeapSize, the Java Virtual Machine's (JVM) memory management decides the initial Java heap size using the InitialRAMPercentage setting. The default has been 1/64 of the system's physical RAM. This behavior results in large initial Java heap sizes on modern systems with a substantial amount of memory, increasing JVM startup times due to necessary initialization of Java heap-related internal data structures.
This change removes the default value of InitialRAMPercentage. Now, if the user does not specify an initial Java heap size, the JVM sets the initial heap size to the minimum possible heap size, which equals to MinHeapSize. This improves startup performance for default JVM configurations by reducing internal memory initialization.
To get the previous behavior, users can explicitly set InitialRAMPercentage to the original value of 1.5625, or configure the initial Java heap size directly using the -Xms or -XX:InitialHeapSize options.
The size of eden and survivor spaces inside of a young generation is governed by SurvivorRatio. These sizes can change whenever the young generation size is updated.
After this change, if the heap is almost full, Serial GC will try everything to expand eden in order to satisfy the allocation request. This can cause eden size to grow beyond the limit determined by SurvivorRatio.
This new behavior may avoid OutOfMemoryExceptions in very tight heap situations that would previously often terminate the VM.
The following JVMTI spec sections have been updated to be made more clear and consistent with regards to which cases the JVMTI_ERROR_OPAQUE_FRAME error code can be returned: PopFrame, NotifyFramePop, ForceEarlyReturn<Type>, GetLocal<Type>, SetLocal<Type>, and the description of the JVMTI_ERROR_OPAQUE_FRAME error code.
The internal representation of native method pointers, jmethodID, has been changed to no longer be a pointer to the JVM representation of the method. Native code that breaks the abstraction of jmethodID to assume this representation will stop working in JDK 26. jmethodID is now a unique identifier that the JVM maps to the native JVM Method.
jcmd command will be available in the headless JDK RPM instead of the headful JDK RPM.
It will be added to the java alternatives group instead of the javac alternatives group.
For the JDK11+ LTS families, the JDK will install into a version-specific installation directory by default. The installation directory of 11+ will have a - before the version-specific string to keep consistency with the past 11+ conventions per family. A junction, also known as a symlink for Windows, will also be created in a "latest" directory. It will point to the latest version of that family. Here is a breakdown example of installation and junction locations 11+ families:
| Version | Installation Directory | Junction location |
|---|---|---|
| jdk25.0.2 | C:\Program Files\Java\jdk-25.0.2 | C:\Program Files\Java\latest\jdk-25 |
| jdk17.0.18 | C:\Program Files\Java\jdk-17.0.18 | C:\Program Files\Java\latest\jdk-17 |
| jdk11.0.30 | C:\Program Files\Java\jdk-11.0.30 | C:\Program Files\Java\latest\jdk-11 |
Each junction will always point to the latest JDK of the matching LTS family. The junction for each family will be removed when the last JDK of the matching LTS family is uninstalled.
The JDK PKCS12 KeyStore implementation now supports the more modern PBMAC1 algorithm for integrity protection. To use the PBMAC1 algorithm, set the "keystore.pkcs12.macAlgorithm" property in the java.security configuration file to a PBMAC1 algorithm. For example, "PBEWithHmacSHA256". Existing PKCS12 keystore files will continue to use the integrity algorithm it was created with, but new keystore files will use the PBMAC1 algorithm.
In a future JDK release, the default value of the "keystore.pkcs12.macAlgorithm" security property will be changed to a PBMAC1 algorithm.
The JDK will stop trusting TLS server certificates issued after March 17, 2026 and anchored by Chunghwa root certificates, in line with similar plans announced by Google and Mozilla.
TLS server certificates issued on or before March 17, 2026 will continue to be trusted until they expire. Certificates issued after that date, and anchored by the Certificate Authority listed in the table below, will be rejected.
The restrictions are enforced in the JDK implementation (the SunJSSE Provider) of the Java Secure Socket Extension (JSSE) API. A TLS session will not be negotiated if the server's certificate chain is anchored by any of the Certificate Authorities in the table below and the certificate has been issued after March 17, 2026.
An application will receive an exception with a message indicating the trust anchor is not trusted, for example:
"TLS Server certificate issued after 2026-03-17 and anchored by a distrusted legacy Chunghwa root CA:
OU=ePKI Root Certification Authority, O="Chunghwa Telecom Co., Ltd." C=TW"
The JDK can be configured to trust these certificates again by removing "CHUNGHWA_TLS" from the jdk.security.caDistrustPolicies security property in the java.security configuration file.
The restrictions are imposed on the following Chunghwa Root certificates included in the JDK:
| Distinguished Name | SHA-256 Fingerprint |
|---|---|
| OU=ePKI Root Certification Authority, O="Chunghwa Telecom Co., Ltd.", C=TW |
C0:A6:F4:DC:63:A2:4B:FD:CF:54:EF:2A:6A:08:2A:0A:72:DE:35:80:3E:2F:F5:FF:52:7A:E5:D8:72:06:DF:D5 |
You can also use the keytool utility from the JDK to print out details of the certificate chain, as follows:
keytool -v -list -alias <your_server_alias> -keystore <your_keystore_filename>
If any of the certificates in the chain are issued by one of the root CAs in the table above are listed in the output you will need to update the certificate or contact the organization that manages the server.
The tools and KeyStore APIs have been updated to warn users when legacy JKS and JCEKS keystores are used, as they use outdated cryptographic algorithms and will be removed in a future release. Users are instead advised to migrate to a PKCS12 keystore using the keytool -importkeystore command.
The following changes have been made:
keytool has been updated to warn of the removal of the JKS and JCEKS keystores.jarsigner has been updated to emit a warning when a JKS or JCEKS keystore is used.KeyStore.load() and KeyStore.store() APIs have been updated to emit a debug warning when operating on a JKS or JCEKS keystore and -Djava.security.debug=keystore is enabled.All warnings inform the user that JKS and JCEKS use outdated cryptographic algorithms and will be removed in a future release. Users are advised to migrate to a PKCS12 keystore.
A new system and security property, com.sun.security.allowedAIALocations, has been introduced. This property allows users the ability to define one or more filtering rules to be applied to URIs obtained from the authority info access extension on X.509 certificates. These filter rules are applied specifically to the CA issuers access method. Any CA issuers URIs in X.509 certificates are only followed when the com.sun.security.enableAIAcaIssuers system property is enabled and the filter allows the URI.
In order to set the rules, the user must set either the com.sun.security.allowedAIALocations security property or the system property by the same name. If the system property has a value, it will override the security property. By default the property is blank, which enacts a deny-all ruleset.
For either property, the value consists of a set of space-separated rules that take the form of a URI, with the following constraints:
/ab/cd/ will match a CA issuer path of /ab/cd/, /ab/cd/ef and /ab/cd/ef/ghi.).For the properties, a single value of "any" (case-insensitive) will create an allow-all rule.
This feature delivers new intrinsics using AVX2 instructions on x86_64 platforms for the ML-DSA signature algorithm in the SUN security provider. This feature also improves the existing AVX512 intrinsics for the ML-DSA algorithm. This optimization is enabled by default on supporting x86_64 platforms. It may be disabled by providing the -XX:+UnlockDiagnosticVMOptions -XX:-UseDilithiumIntrinsics command-line options.
The Cipher.getInstance(String) method is declared to throw NoSuchPaddingException and NoSuchAlgorithmException. In prior releases, NoSuchPaddingException is never thrown and is instead wrapped inside a NoSuchAlgorithmException as the cause. This issue has been fixed and NoSuchPaddingException is thrown directly.
The output of java -XshowSettings:security:tls has been updated to include the list of enabled named groups and the list of enabled signature schemes used for SSL/TLS/DTLS handshakes.
XML signatures that use XPath transforms have been disabled by default. The XPath transform is not recommended by the XML Signature Best Practices document. Applications should use the XPath Filter 2.0 transform instead, which was designed to be an alternative to the XPath transform. If necessary, and at their own risk, applications can workaround this policy by modifying the jdk.xml.dsig.secureValidationPolicy security property and re-enabling the XPath transform. See the definition of this security property in the java.security file for more information.
Prior to JDK 26, the javac compiler did not apply a JLS mandated capture conversion when deciding if a method reference is compatible with a given function type. This could lead the javac compiler to accept code like the following:
import java.util.function.Supplier;
class Test {
interface X<T> {
X<T> self();
}
static X<?> makeX() {return null;}
static <R> X<R> create(Supplier<? extends R> supplier) {return null;}
static X<X<?>> methodRef() {
return create(Test::makeX).self();
}
}
Starting from JDK 26, the javac compiler will apply the JLS mandated capture conversion when deciding if a method reference is compatible with a given function type. Code, like that in the sample above, will be rejected.
The jlink tool can be used to assemble a set of modules and their dependences into a custom runtime image for a different OS, architecture, or JDK version to the JDK containing the jlink tool. This is sometimes referred to as "cross linking".
The version checking used when cross linking is changed to be more strict than in previous releases. When cross linking, the set of standard and JDK modules for the custom runtime must exactly match the version and vendor of the JDK containing the jlink tool. This strict checking is necessary due to the pipeline of jlink plugins that transform and optimize the classes and resources that go into the image. The jlink tool cannot reliably generate a run-time image when they don't match exactly.
In previous releases the version checking was less strict and allowed jlink running on JDK $N.0.$U from vendor $X create a run-time image from a set of modules for JDK $N.0.$V from vendor $Y. The strict checking means that the value of $U and $V must be equal, and that $X and $Y be equal.
The Java launcher now rejects source programs with a private no-arg constructor, which matches what the Java launcher does in normal class mode.
The JDK XPath implementation now supports External Access Properties. It also enables restriction through these properties when secure processing is set to true explicitly. To secure an XPath processor against risky evaluation of external DTD references, enable secure processing as demonstrated in the following code:
XPathFactory xf = XPathFactory.newInstance();
xf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
This process will cause the XPath processor created via the factory to throw XPathExpressionException if used to evaluate a raw XML document that contains external references such as an external DTD.
Mitigation includes using the External Access Properties to override that enabled by FSP. For example, the following setting will allow the process to continue when there is a reference to a file-based external DTD in the XML document:
xf.setProperty(ACCESS_EXTERNAL_DTD, "file");
It is recommended that applications use the XPath processor to evaluate DOM rather than raw XML documents.
See The FEATURE_SECURE_PROCESSING Security Directive and External Access Properties for more information.
At VM exit, -Xlog:cpu now prints a table breaking down VM CPU usage into components.
For example:
[62.719s][info][cpu] === CPU time Statistics =============================================================
[62.719s][info][cpu] CPUs
[62.719s][info][cpu] s % utilized
[62.719s][info][cpu] Process
[62.719s][info][cpu] Total 410.2789 100.00 6.5
[62.719s][info][cpu] Garbage Collection 124.8134 30.42 2.0
[62.719s][info][cpu] GC Threads 124.5082 30.35 2.0
[62.719s][info][cpu] VM Thread 0.3052 0.07 0.0
[62.719s][info][cpu] =====================================================================================
In above example, the JVM process took 410.3s of CPU time, with on average 6.5 CPU cores utilized. Of that, 124.8s, that is around 30% of the time has been attributed to garbage collection.
Due to an oversight when BigDecimal.sqrt was first added to the platform, its preferred scale was defined as argumentScale / 2 rather than ceilDiv(argumentScale, 2). For many argumentScale's these expression are equivalent, but for odd and positive scales they differ by 1. The latter definition aligns with the analagous concept for decimal floating-point types specified by the IEEE 754 floating-point standard and Java SE 26 is changed to use this latter definition.
Before and after this change, numerically equal results will be returned; that is oldResult.compareTo(newResult) == 0. If the results differ, they will only differ in their representation (for example 10 vs 1e1). In more detail, if the scale of the argument is even, the preferred scale is the same before and after this change. If the scale of the argument is odd and negative, the preferred scale is the same before and after this change. Additionally, the result may still be the same even when the scale of argument is odd and positive since the scale is only preferred and the scale of the result is also a function of other factors, including the precision being used for the computation.
Although we have stated the goal to have Oracle JDK and OpenJDK binaries be as close to each other as possible, there remain several differences between the two options.
The current differences are:
msi, rpm, deb, etc.) which not only place the JDK binaries in your system but also contain update rules and in some cases handle some common configurations like set common environmental variables (such as, JAVA_HOME in Windows) and establish file associations (such as, use java to launch .jar files). OpenJDK is offered only as compressed archive (tar.gz or .zip).java -version is different. Oracle JDK returns java and includes the Oracle-specific identifier. OpenJDK returns OpenJDK and does not include the Oracle-specific identifier.\legal\java.desktop\freetype.md is therefore different.