JDK 28 Early-Access Release Notes

Latest Update: 2026-10-16
This is a draft of the release notes that will accompany OpenJDK JDK 28. The contents are subject to change until release.

Notable Features

401: Value Objects (Preview)

Introduce value objects, which are immutable and lack object identity. Value objects are distinguished solely by the values of their fields, and can be represented by Java Virtual Machines in ways that improve performance. This is a preview language and VM feature.

539: Strict Field Initialization in the JVM (Preview)

Introduce strictly-initialized fields in the Java Virtual Machine. Such fields must be initialized before they are read, thus default values such as 0 or null are never observed. For strictly-initialized fields that are final, the same value is always observed. This is a preview VM feature, available for use by compilers that emit class files.

540: Simple JSON API (Incubator)

Define a simple, standard API for parsing and generating JSON documents so that doing so does not require an external library. Enable many JSON processing tasks to be accomplished with little coding. This is an incubating API.

542: PEM Encodings of Cryptographic Objects

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.

544: Ahead-of-Time Code Compilation

Improve startup and warmup time by making optimized native code for an application instantly available when the HotSpot Java Virtual Machine starts. Achieve this by compiling application code to native code in a training run, storing the native code in the AOT cache for use in subsequent production runs. If the workload changes in production, regenerate native code dynamically for continued peak performance, providing the best of both ahead-of-time (AOT) and just-in-time (JIT) compilation.

Build 20

Added Certum Trusted Root CA and Certum EC-384 CA Certificates (JDK-8392771)

security-libs/java.security

The following root certificates have been added to the cacerts truststore:

+ Certum
  + certumtrustedrootca
    DN: CN=Certum Trusted Root CA, OU=Certum Certification Authority, O=Asseco Data Systems S.A., C=PL

+ Certum
  + certumec384ca
    DN: Certum EC-384 CA, OU=Certum Certification Authority, O=Asseco Data Systems S.A., C=PL

Removal of sun.cpu.isalist System Property (JDK-6340855)

core-libs/java.lang

The property sun.cpu.isalist has been removed.

The property was originally introduced in JDK 1.3 to report the available CPU instruction sets on Solaris. On other systems the property was never fully implemented.

Launching of application in Desktop.browse() is disabled by default (JDK-8377972)

client-libs

A new implementation System Property (awt.desktop.browse_insecure) is provided to partially re-enable previous behaviour of the java.awt.Desktop.browse() API. This is an opt-in property, and the value is a comma-separated list of URL schemes.

Eg :

-Dawt.desktop.browse_insecure=file,ftps,myapp

Background : On Windows and macOS platforms, the historic behaviour of the java.awt.Desktop.browse() API was to invoke platform APIs, rather than directly invoking the default browser.

Since this behavior is now disabled, applications registered with the platform desktop may no longer be launched unless the browser also supports launching the application.

Usage : As a specific example on Windows, the new behaviour is that invoking a file:/// URL will display in the browser.

To re-enable the previous behaviour of launching the Windows Explorer application, on the command line specify

-Dawt.desktop.browse_insecure=file

To re-enable all schemes the application should specify a wild card value, which should be used with extreme caution

-Dawt.desktop.browse_insecure=*

Build 18

Entrust G4 Root CA Removed (JDK-8386371)

security-libs/java.security

The following root certificate has been removed from the cacerts keystore:

+ alias name "entrustrootcag4 [jdk]"
  Distinguished Name: CN=Entrust Root Certification Authority - G4, OU="(c) 2015 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US

Build 17

javac Correctly Types Conditional and Switch Expressions Mixing Raw and Parameterized Types (JDK-8385925)

tools/javac

Prior to JDK 28, javac could incorrectly determine the type of a standalone reference conditional or switch expression when its result expressions mixed raw and parameterized types. In some cases, whether the code compiled depended on the order of those expressions. For example, the following code was previously accepted, erroneously, because javac used unchecked assignment conversion and selected List<Integer> as the type of the conditional expression. However, if this code included b ? raw : parameterized (the alternative ordering), it was correctly rejected.:

import java.util.List;

class Test {
    Integer first(boolean b, List raw, List<Integer> parameterized) {
        return (b ? parameterized : raw).get(0);
    }
}

Starting with JDK 28, javac determines the type of these expressions according to the Java Language Specification. As a result, code that previously compiled only because a parameterized expression appeared before a raw expression may now be rejected. For example, in the previous example, in (b ? parameterized : raw).get(0), the expression has raw type List, so get(0) has type Object and cannot be safely converted to Integer.

Build 16

The Java Compiler Now Performs Exception and Reachability Analyses on Switch Guards (JDK-8390759)

tools/javac

javac now

  • rejects source code when a switch guard throws a checked exception that is neither caught nor declared
  • rejects source code when a switch guard contains a statement that is unreachable.

ML-DSA in TLS 1.3 (JDK-8381641)

security-libs/javax.net.ssl

SunJSSE now supports the TLS 1.3 ML-DSA signature schemes mldsa65, mldsa87, and mldsa44. With this support, TLS 1.3 in the JDK can use ML-DSA end-entity certificates and ML-DSA CertificateVerify signatures for authentication.

These schemes are placed at the front of the SunJSSE default signature scheme preference list in the following order: mldsa65, mldsa87, and mldsa44.

This support applies only to TLS 1.3.

Build 14

Default PKCS12 Mac Algorithm Is Now PBMAC1 (JDK-8370245)

security-libs/java.security

The default value of the keystore.pkcs12.macAlgorithm security property is now PBEWithHmacSHA256. Newly created PKCS #12 keystores use PBMAC1 integrity protection, a more modern and extensible mechanism.

RSA/ECB/PKCS1Padding Is Now a Legacy Algorithm (JDK-8388138)

security-libs/java.security

The default JDK security configuration now classifies Cipher.RSA/ECB/PKCS1Padding as a legacy algorithm by adding it to the jdk.crypto.legacyAlgorithms security property. The algorithm remains available, but its use will generate a runtime warning indicating that the algorithm is considered legacy and may be disabled in a future release.

Build 13

Improved ML-DSA Performance (JDK-8381223)

security-libs/java.security

The Java implementation of the ML-DSA signature algorithm has been optimized. Signing and verification are faster on platforms that use the Java implementation. Performance is also improved on platforms with ML-DSA intrinsics enabled.

Build 9

jlink --strip-debug` now removes external debug symbol files (.debuginfo, .diz, .dSYM, .pdb) (JDK-8387324)

tools/jlink

jlink --strip-debug now removes external debug symbol files (.debuginfo, .diz, .dSYM, .pdb)

The jlink --strip-debug option previously only stripped embedded native debug symbols from executables and shared libraries (i.e. debug info stored inside the binary itself). When a JDK was built with --with-native-debug-symbols=external — the default for fastdebug and debug builds — the accompanying .debuginfo and .diz files were silently copied into the resulting image, leaving debug information present despite the intent of --strip-debug.

The option now consistently excludes external debug symbol files (.debuginfo and .diz) from the generated image on Linux, regardless of how the source JDK was built. The behavior for builds using --with-native-debug-symbols=internal is unchanged.

CachedRowSet Warns Once On Max Rows (JDK-8388810)

core-libs/java.sql

The JDK implementation for javax.sql.CachedRowSet.populate(ResultSet) now reports at most a single warning when the maximum rows (configured with javax.sql.RowSet.setMaxRows(int)) is exceeded. Previously, a new warning was chained for each additional row past the maximum. The behavior of javax.sql.CachedRowSet.populate(ResultSet, int) remains unchanged, as it correctly reported a single warning.

The JDK implementation for javax.sql.CachedRowSet.getRowSetWarnings() has been updated so that the root warning contains a message. Previously, the root warning returned by this method had an empty message. Additionally, the method now correctly returns null when there are no warnings present in the CachedRowSet.

Build 8

Allow configuration of the JVM's temporary directory on Linux (JDK-8384557)

hotspot/runtime

An advanced serviceability option has been added to the JVM to allow configuration of an alternate temporary directory on Linux.

-XX:AltTempDir=/path

On Linux, the usual directory to use for temporary files is /tmp. In some secure container environments however, /tmp is made read-only and so is unusable by the VM for its temporary files. To accommodate this uncommon circumstance the -XX:AltTempDir flag can be used to tell the VM to use a different temporary directory.

See the java man page under ADVANCED SERVICEABILITY OPTIONS FOR JAVA for more details.

Specification of sun.net.httpserver.maxReqTime and sun.net.httpserver.maxRspTime System Properties Corrected to State Their Values are in Seconds (JDK-8387598)

core-libs/java.net

The specification of the sun.net.httpserver.maxReqTime and sun.net.httpserver.maxRspTime system properties, which are used to configure the HTTP server in the jdk.httpserver module, has been corrected to state that their values are in seconds. This change updates the specification to match the long standing behaviour in the implementation.

java.sql.Date and java.sql.Timestamp Preserve BC Years in java.time Conversions (JDK-8272194)

core-libs/java.sql

The java.sql.Date.toLocalDate() and java.sql.Timestamp.toLocalDateTime() conversions now preserve BC years correctly. Previously, if the underlying SQL date or timestamp contained a BC year, these conversions would incorrectly return a result containing an AD year. For example, a java.sql.Date representing January 1, 2 BC would be converted to a java.time.LocalDate of 0002-01-01. After this change, that same value is now correctly converted to -0001-01-01.

Applications that convert BC java.sql.Date or java.sql.Timestamp values will now observe the corrected year in the resulting java.time value. Conversions of AD values will remain unchanged.

java -XshowSettings Exits Normally When Used Without a Java Application (JDK-8387750)

tools/launcher

The java -XshowSettings option now exits with status 0 when used without a Java application. After displaying the requested settings, the launcher no longer prints the general usage information.

Build 7

Changed HttpCookie to Accept Cookies With Invalid Expires Attribute As Session Cookies (JDK-8380549)

core-libs/java.net

java.net.HttpCookie will ignore the value of the Expires attribute of a cookie, if the attribute value cannot be parsed into a valid date. Such cookies do not expire till the end of the session. This new behaviour matches the Expires attribute specification of RFC-6265.

Previously, the failure to parse the value of the Expires attribute would have resulted in the cookie being discarded.

Build 5

cacerts jlink plugin (JDK-8377102)

security-libs/java.security

A new jlink plugin has been added which allows the user to specify the specific CA (Certificate Authority) certificates to include in the cacerts keystore in a custom runtime image. This is very useful for creating runtimes that only contain the CA certificates that are needed by applications which will be using that custom runtime. The command-line syntax takes one or more cacerts keystore aliases as an option, separated by a comma.

For example:

jlink --cacerts "letsencryptisrgx1 jdk (link not found)"

or

jlink --cacerts "letsencryptisrgx1 jdk(link not found),digicertglobalrootcajdk (link not found)"

LuxTrust Global Root CA Removed (JDK-8387123)

security-libs/java.security

The following root certificate has been removed from the cacerts keystore:

+ alias name "luxtrustglobalrootca [jdk]"
  Distinguished Name: CN=LuxTrust Global Root, O=LuxTrust s.a., C=LU

Significant performance gains in X25519 key agreement and Ed25519 signature algorithms (JDK-8385304, JDK-8371305, JDK-8385304)

security-libs/javax.crypto

The underlying Curve25519 operations have been provided intrinsics in this release which has resulted in noticeable performance improvements for the X25519 key agreement algorithm and the Ed25519 signature algorithm as follows:

  1. x86-64 architecture

    • X25519 Key generation: +19%
    • X25519 Decapsulation: +19%
    • X25519 Encapsulation: +19%
    • Ed25519 Key generation: +20%
    • Ed25519 Signing: +19%
    • Ed25519 Verification: +16%
  2. AArch64 architecture

    • X25519 Key generation: +10%
    • X25519 Decapsulation: +9%
    • X25519 Encapsulation: +9%
    • Ed25519 Key generation: +15%
    • Ed25519 Signing: +12%
    • Ed25519 Verification: +12%

Build 3

Capture Named Group information in TLSHandshakeEvent (JDK-8301626)

security-libs/javax.net.ssl

The jdk.TLSHandshakeEvent JFR event now records the named group that is negotiated in a TLS handshake. A new field named namedGroup has been added to the event.

Build 2

ListFormat Single Quote Handling Fixed (JDK-8386200)

core-libs/java.text

The JDK reference implementation for java.text.ListFormat is no longer affected by java.text.MessageFormat single quote escaping semantics. For example, previously, a list pattern such as " '{0}', {1} " may have incorrectly formatted List.of("bar", "foo") as: " {0}, bar ". ListFormat is now updated to always treat single quotes as literal characters when read from a pattern.

This change is observable for ListFormat patterns that contain single quotes. As a result, it primarily affects application-supplied custom patterns that contain them.

Custom ListFormat Patterns Are Validated More Strictly (JDK-8385834)

core-libs/java.text

java.text.ListFormat.getInstance(String[]) now validates custom list format patterns more strictly. Only the exact placeholders "{0}", "{1}", and "{2}" are accepted, and "{2}" is accepted only in the three-element pattern. Patterns with duplicate placeholders or curly braces outside valid placeholders now cause an IllegalArgumentException to be thrown.

This change affects only application-supplied custom patterns passed to ListFormat.getInstance(String[]). Locale-derived ListFormat instances are not affected.