JDK 22 Release Notes


JEP 423 Region Pinning for G1

Reduce latency by implementing region pinning in G1, so that garbage collection need not be disabled during Java Native Interface (JNI) critical regions.

For more information: JEP 423: Region Pinning for G1

JEP 447 Statements before super(...) (Preview)

In constructors in the Java programming language, allow statements that do not reference the instance being created to appear before an explicit constructor invocation. This is a preview language feature.

JEP 454 Foreign Function & Memory API

Introduce an API by which Java programs can interoperate with code and data outside of the Java runtime. By efficiently invoking foreign functions (i.e., code outside the JVM), and by safely accessing foreign memory (i.e., memory not managed by the JVM), the API enables Java programs to call native libraries and process native data without the brittleness and danger of JNI.

For more information: JEP 454: Foreign Function & Memory API

JEP 456 Unnamed Variables & Patterns

Enhance the Java programming language with unnamed variables and unnamed patterns, which can be used when variable declarations or nested patterns are required but never used. Both are denoted by the underscore character, _.

JEP 457 Class-File API (Preview)

Provide a standard API for parsing, generating, and transforming Java class files. This is a preview API.

JEP 458 Launch Multi-File Source-Code Programs

Enhance the java application launcher to be able to run a program supplied as multiple files of Java source code. This will make the transition from small programs to larger ones more gradual, enabling developers to choose whether and when to go to the trouble of configuring a build tool.

JEP 459 String Templates (Second Preview)

Enhance the Java programming language with string templates. String templates complement Java's existing string literals and text blocks by coupling literal text with embedded expressions and template processors to produce specialized results. This is a preview language feature and API.

JEP 460 Vector API (Seventh Incubator)

Introduce an API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPU architectures, thus achieving performance superior to equivalent scalar computations.

JEP 461 Stream Gatherers (Preview)

Enhance the Stream API to support custom intermediate operations. This will allow stream pipelines to transform data in ways that are not easily achievable with the existing built-in intermediate operations. This is a preview API.

JEP 462 Structured Concurrency (Second Preview)

Simplify concurrent programming by introducing an API for structured concurrency. Structured concurrency treats groups of related tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. This is a preview API.

JEP 463 Implicitly Declared Classes and Instance Main Methods (Second Preview)

Evolve the Java programming language so that students can write their first programs without needing to understand language features designed for large programs. Far from using a separate dialect of the language, students can write streamlined declarations for single-class programs and then seamlessly expand their programs to use more advanced features as their skills grow. This is a preview language feature.

JEP 464 Scoped Values (Second Preview)

Introduce scoped values, which enable managed sharing of immutable data both with child frames in the same thread, and with child threads. Scoped values are easier to reason about than thread-local variables and have lower space and time costs, especially when used in combination with Virtual Threads and Structured Concurrency. This is a preview API.

New Features

New Security Category for -XshowSettings Launcher Option (JDK-8281658)


The -XshowSettings launcher has a new security category. Settings from security properties, security providers and TLS related settings are displayed with this option. A security sub-category can be passed as an argument to the security category option. See the output from java -X:

       show all security settings and continue
       show settings for the specified security sub-category and continue. Possible *sub-category* arguments for this option include:
       all: show all security settings and continue
       properties: show security properties and continue
       providers: show static security provider settings and continue
       tls: show TLS related security settings and continue

Third party security provider details will be reported if they are included in the application class path or module path and such providers are configured in the java.security file.

HSS/LMS: keytool and jarsigner Changes (JDK-8302233)


The jarsigner and keytool tools have been updated to support the Hierarchical Signature System/Leighton-Micali Signature (HSS/LMS) signature algorithm. jarsigner supports signing JAR files with HSS/LMS and verifying JAR files signed with HSS/LMS while keytool supports generating HSS/LMS key pairs.

The JDK includes a security provider that supports HSS/LMS signature verification only. In order to use the key pair generation and signing features of keytool and jarsigner, a third-party provider that supports HSS/LMS key pair and signature generation and a keystore implementation that can store HSS/LMS keys is required.

Even though there’s no specific Java SE API to initialize an HSS/LMS key pair generator, keytool can function with a third-party KeyPairGenerator implementation that supports initialization via an integer keysize or a NamedParameterSpec object. In such cases, users are able to provide the parameters using the existing -keysize or -groupname options of keytool.

As part of this change, the JAR specification was modified to repurpose the existing “.DSA” extension for JAR files signed with HSS/LMS and other forthcoming signature algorithms.

The inheritDoc Tag and Method Comments Algorithm Have Been Changed (JDK-8285368)


An optional parameter has been added to the inheritDoc tag so that an author can specify the supertype from which to search for inherited documentation. Additionally, the algorithm to search for inherited documentation has been modified to better align with the method inheriting and overriding rules in Java Language Specification.

For more details, see the following sections of the Documentation Comment Specification for the Standard Doclet:

Support Unicode 15.1 (JDK-8296246)


This release upgrades the Unicode version to 15.1, which includes updated versions of the Unicode Character Database and Unicode Standard Annexes #9, #15, and #29:

  • The java.lang.Character class supports the Unicode Character Database, which adds 627 characters, for a total of 149,813 characters. The addition includes one new UnicodeBlock, which consists of urgently needed CJK ideographs, synchronized with planned additions to the Chinese national standard, GB 18030.
  • The java.text.Bidi and java.text.Normalizer classes support Unicode Standard Annexes, #9 and #15, respectively.
  • The java.util.regex package supports Extended Grapheme Clusters based on the Unicode Standard Annex #29.

For more details about Unicode 15.1, refer to the Unicode Consortium’s release note.

JEP 454: Foreign Function & Memory API ( JEP 454)


The Foreign Function & Memory API allows Java programs to interoperate with code and data outside of the Java runtime.

Access to foreign memory is realized via the MemorySegment class. A memory segment is backed by a contiguous region of memory, located either off-heap or on-heap. Safe and deterministic deallocation of off-heap memory segments is provided via the Arena class. Structured access to memory segments is realized via the MemoryLayout class. A memory layout can be used to compute the size and offsets of struct fields, and to obtain var handles that read and write the data in memory segments.

Access to foreign functions is realized via the Linker class. The native linker can be used to obtain method handles that provide a fast way for Java code to invoke native code. Native code is invoked using the calling convention for the OS and processor where the Java runtime is executing, so Java code is not polluted with platform-specific details. Native code can also call back into Java code.

Native code is generally unsafe; if used incorrectly, it might crash the JVM or result in memory corruption. Some of the methods in the Foreign Function & Memory API are considered unsafe because they provide access to native code. These unsafe methods are restricted, which means their use is permitted but causes warnings at run time. Developers can compile their code with -Xlint:restricted to learn if it will produce warnings at run time due to use of unsafe methods.

If the risks associated with native code are understood, then unsafe methods can be used without warnings at run time by passing --enable-native-access=... on the java command line. For example, java --enable-native-access=com.example.myapp,ALL-UNNAMED ... enables warning-free use of unsafe methods by code in the com.example.myapp module and code on the class path (denoted by ALL-UNNAMED). Additionally, in an executable JAR, the manifest attribute Enable-Native-Access: ALL-UNNAMED enables warning-free use of unsafe methods by code on the class path; no other module can be specified. When the --enable-native-access option or JAR manifest attribute is present, any use of unsafe methods by code outside the list of specified modules causes an IllegalCallerException to be thrown, rather than a warning to be issued.

TCP_KEEPxxxx Extended Socket Options Are Now Supported on the Windows Platform (JDK-8308593)


The java.net.ExtendedSocketOptions TCP_KEEPIDLE and TCP_KEEPINTERVAL are supported on Windows platforms starting from Windows 10 version 1709 and onwards. TCP_KEEPCOUNT is supported starting from Windows 10 version 1703 and onwards.

New Constants for 32-bit UTF Charsets (JDK-8310047)


The following three new constants in java.nio.charset.StandardCharsets class have been introduced:


These are 32-bit based UTF charsets that are in parallel with the existing 8-bit and 16-bit equivalents.

Locale-Dependent List Patterns (JDK-8041488)


A new class, ListFormat, which processes the locale-dependent list patterns has been introduced, based on Unicode Consortium's LDML specification. For example, a list of three Strings: "Foo", "Bar", "Baz" is typically formatted as "Foo, Bar, and Baz" in US English, while in French it is "Foo, Bar et Baz." The following code snippet does such formatting:

ListFormat.getInstance().format(List.of("Foo", "Bar", "Baz"))

Besides the default concatenation type STANDARD (= and), the class provides two additional types, OR for "or" concatenation, and UNIT for concatenation suitable for units for the locale.

Add equiDoubles() Method to java.util.random.RandomGenerator. (JDK-8302987)


A new method, equiDoubles(), has been added to java.util.random.RandomGenerator.

equiDoubles() guarantees a uniform distribution, provided the underlying nextLong(long) method returns uniformly distributed values, that is as dense as possible. It returns a DoubleStream rather than individual doubles because of slightly expensive initial computations. They are better absorbed as setup costs for the stream rather than being repeated for each new computed value.

The aim is to overcome some numerical limitations in the families of doubles() and nextDouble() methods. In these, an affine transform is applied to a uniformly distributed pseudo-random value in the half-open interval [0.0, 1.0) to obtain a pseudo-random value in the half-open interval [origin, bound). However, due to the nature of floating-point arithmetic, the affine transform ends up in a slightly distorted distribution, which is not necessarily uniform.

Changes to java.util.concurrent.ForkJoinPool and ForkJoinTask (JDK-8288899)


A new method, invokeAllUninterruptibly(Collection), is added to java.util.concurrent.ForkJoinPool as an uninterruptible version of invokeAll(Collection).

The pre-existing invokeAll(Collection) method is defined by ExecutorService to throw InterruptedException. The override of this method in ForkJoinPool did not declare InterruptedException. As part of the changes, the override of this method has been removed from ForkJoinPool. Existing code that is compiled to use ForkJoinPool.invokeAll will no longer compile without change. Code that does not wish to handle interruption can be changed to use invokeAllUninterruptibly.

New methods adaptInterruptible(Runnable) and adaptInterruptible(Runnable, Object) are added to java.util.concurrent.ForkJoinTask to support adaptation of runnable tasks that may handle interruption.

As part of the changes in this release, the Future objects returned by the ForkJoinPool.submit(Runnable) and ForkJoinPool.submit(Callable) are changed to align with other implementations of ExecutorService. More specifically:

  • Future.cancel(true) will interrupt the thread running the task if cancelled before the task has completed.
  • Future.get will throw ExecutionException with the exception as the cause if the task fails. Previous behavior was to throw ExecutionException with a RuntimeException as the cause.

Parallel: Better GC Throughput with Large Object Arrays (JDK-8321013)


During a young collection, Parallel GC searches for dirty cards in the card table to locate old-to-young pointers. After finding dirty cards, Parallel GC uses the internal bookkeeping data structures to locate object starts for heap-parsing to be able to walk the heap within these dirty cards object-by-object.

This change modifies the internal bookkeeping data structure to the one used by Serial and G1. As a result, the object start lookup time is improved and one can observe about a 20% reduction of Young-GC pause in some benchmarks using large object arrays.

Parallel: Precise Parallel Scanning of Large Object Arrays for Young Collection Roots (JDK-8310031)


During young collection, ParallelGC partitions the old generation in 64kB stripes when scanning it for references into the young generation. These stripes are assigned to worker threads that do the scanning in parallel as work units.

Before this change Parallel GC always scanned these stripes completely even if only a small part had been known to contain interesting references. Additionally every worker thread processed the objects that start in that stripe by itself including any part of objects that extend into other stripes. This behavior limited parallelism when processing large objects: a single large object potentially containing thousands of references had been scanned by a single thread only and in full, and would also cause bad scaling due to memory sharing and cache misses in the subsequent long work stealing phase.

With this change, Parallel GC workers limit work to their stripe, and only process interesting parts of large object arrays. This reduces work done by a single thread for a stripe, improves parallelism and reduces the amount of work stealing. Parallel GC pauses is now on par with G1 in presence of large object arrays, reducing pause times by 4-5 times in some cases.

Serial: Better GC Throughput with Scarce Dirty Cards (JDK-8319373)


During a young collection, Serial GC searches for dirty cards in the card table to locate old-to-young pointers. After finding dirty cards, Serial GC uses the block offset table to locate object starts for heap-parsing to be able to walk the heap within these dirty cards object-by-object.

This change improves the object start lookup and search for dirty cards resulting in a large (~40%) reduction in Young-GC pause in some benchmarks using large object arrays.

G1: Balance Code Root Scan Phase during Garbage Collection (JDK-8315503)


The Code Root Scan Phase during garbage collection finds references to Java objects in compiled code. To speed up this process, G1 maintains a remembered set for compiled code that contains references into the Java heap. That is, every region contains a set of compiled code that contains references into it.

Assuming that such references are few, previous code used a single thread per region to iterate over a particular region's references, which poses a scalability bottleneck if the distribution of these references is very unbalanced.

G1 now distributes this code root scan work across multiple threads within regions, removing this bottleneck.

G1: Fast Collection of Evacuation Failed Regions (JDK-8140326)


G1 now reclaims regions that failed evacuation in the next garbage collection.

When there is not enough space to move Java objects from the collection set, young generation regions for example, to some destination area, or that region has been pinned and contains non-movable Java objects (see [JEP 423]), G1 considers that region to have failed evacuation.

Previously, such regions were moved into the old generation as completely full regions, and left lingering for re-examination until the next complete heap analysis, marking, found them to be reclaimable in the next space reclamation phase. Very often, such regions are sparsely populated because only a very few objects were not relocatable or very few objects were actually pinned.

With this change, G1 considers evacuation failed regions as reclaimable beginning with any subsequent garbage collection. If the pause time permits, G1 will evacuate them in addition to the existing collection set.

This can substantially reduce the time to reclaim these mostly empty regions, decreasing heap pressure and the need for garbage collection activity in the presence of evacuation failed regions.

JEP 423: Region Pinning for G1 ( JEP 423)


This [JEP] reduces latency by implementing region pinning in G1, so that garbage collection need not be disabled during Java Native Interface (JNI) critical regions.

Java threads that use native code do not stall garbage collections any more. Garbage collections will execute regardless of native code keeping references to Java objects. The garbage collection will keep objects that may be accessed by native code in place, collecting garbage only in surrounding heap areas but will be otherwise unaffected.

[JEP]: https://openjdk.org/jeps/423 "JEP 423: Region Pinning for G1"

Update XML Security for Java to 3.0.3 (JDK-8319124)


The XML Signature implementation has been updated to Santuario 3.0.3. Support for four new SHA-3 based RSA-MGF1 SignatureMethod algorithms have been added: SignatureMethod.SHA3_224_RSA_MGF1, SignatureMethod.SHA3_256_RSA_MGF1, SignatureMethod.SHA3_384_RSA_MGF1, and SignatureMethod.SHA3_512_RSA_MGF1.

Add a Built-in Catalog to JDK XML Module (JDK-8306055)


A JDK built-in catalog is introduced to host DTDs defined by the Java Platform. The JDK creates a CatalogResolver based on the built-in catalog when needed to function as the default external resource resolver. When no user-defined resolvers are registered, a JDK XML processor will fall back to the default CatalogResolver and will attempt to resolve an external reference before making a connection to fetch it. The fall-back also takes place if a user-defined resolver exists but allows the process to continue when unable to resolve the resource.

If the default CatalogResolver is unable to locate a resource, it will signal the XML processors to continue processing, or skip the resource, or throw a CatalogException. The action it takes is configured with the jdk.xml.jdkcatalog.resolve property. The new property can be set on factory APIs, as a Java system property, or in the JAXP Configuration File. The new property affects all XML processors uniformly.

For further information, see the JDK built-in Catalog section of the java.xml module summary.

Add a JDK Property for Specifying DTD Support (JDK-8306632)


A new property jdk.xml.dtd.support is introduced that determines how XML processors handle DTDs. The new property can be set on factory APIs, as a Java system property, or in the JAXP Configuration File. The new property affects all XML processors uniformly.

The new property complements the two existing DTD properties: disallow-doctype-decl (fully qualified name: http://apache.org/xml/features/disallow-doctype-decl), which is applicable only to the DOM and SAX processors, and supportDTD (javax.xml.stream.supportDTD), which is applicable only to the StAX processor. When one of these existing properties is set on the respective processor factory, its value will take precedence over any value specified for the jdk.xml.dtd.support property.

For further information, see the Configuration section of the java.xml module summary.

Removed Features and Options

sun.misc.Unsafe.shouldBeInitialized and ensureClassInitialized Are Removed (JDK-8316160)


The shouldBeInitialized(Class) and ensureClassInitialized(Class) methods have been removed from sun.misc.Unsafe. These methods have been deprecated for removal since JDK 15. java.lang.invoke.MethodHandles.Lookup.ensureInitialized(Class) was added in Java 15 as a standard API to ensure that an accessible class is initialized.

Thread.countStackFrames Has Been Removed (JDK-8309196)


The method java.lang.Thread.countStackFrames() has been removed in this release. This method dates from JDK 1.0 as an API for counting the stack frames of a suspended thread. The method was deprecated in JDK 1.2 (1998), deprecated for removal in Java 9, and re-specified/degraded in Java 14 to throw UnsupportedOperationException unconditionally.

java.lang.StackWalker was added in Java 9 as a modern API for walking the current thread's stack.

The Old Core Reflection Implementation Has Been Removed (JDK-8305104)


The new core reflection implementation has been the default since JDK 18 and the old implementation is now removed. The -Djdk.reflect.useDirectMethodHandle=false introduced by JEP 416 to enable the old core reflection implementation becomes a no-op.

Jdeps -profile and -P Option Have Been Removed (JDK-8310460)


Compact profiles became obsolete in Java SE 9 when modules were introduced. The jdeps -profile and -P options were deprecated for removal in JDK 21 and now removed in JDK 22. Customers can use jdeps to find the set of modules required by their applications instead.

Deprecated Features and Options

Deprecation of the jdk.crypto.ec module (JDK-8308398)


The jdk.crypto.ec module is being deprecated with the intent to remove it. An empty module exists as a transition for developers to fix applications or jlink commands with hard-coded dependencies before removal. The SunEC JCE Provider, which provides Elliptic Curve Cryptography, is now in the java.base module. There should be no difference in cryptographic functionality with this deprecation.

sun.misc.Unsafe park/unpark, getLoadAverage, xxxFence methods are deprecated, for removal (JDK-8315938)


The park, unpark, getLoadAverage, loadFence, storeFence, and fullFence methods defined by sun.misc.Unsafe have been deprecated for removal.

Code using these methods should move to java.util.concurrent.LockSupport.park/unpark (Java 5), java.lang.management.OperatingSystemMXBean.getSystemLoadAverage (Java 6), and java.lang.invoke.VarHandle.xxxFence (Java 9).

-Xnoagent Option Is Deprecated for Removal (JDK-8312072)


The -Xnoagent option of the java command has been deprecated for removal. This option has been ignored for many releases and doesn't provide any functionality. It will now generate a deprecation warning when used while launching java.

Any existing code which uses this option should be updated to remove reference to this option.

-Xdebug and -debug Options Are Deprecated for Removal (JDK-8227229)


The -Xdebug and -debug options of the java command have been deprecated for removal. These options have been ignored for several releases and don't provide any functionality. Using either of these options while launching java will now log a deprecation warning.

Existing applications which use either of these options should be updated to remove references to these options.

Notable Issues Fixed

Reimplement MethodHandleProxies::asInterfaceInstance (JDK-6983726)


In previous releases MethodHandleProxies::asInterfaceInstance returns a Proxy instance. MethodHandleProxies::asInterfaceInstance has been reimplemented to return instances of a hidden class that can be unloaded when all instances returned for the same interface becomes unreachable. Once unloaded, subsequent call to MethodHandleProxies::asInterfaceInstance will spin and define a new hidden class that may incur performance overhead.

MethodHandles.Lookup::findStaticVarHandle Does Not Eagerly Initialize the Field's Declaring Class (JDK-8291065)


In the previous releases, MethodHandles.Lookup::findStaticVarHandle eagerly initializes the declaring class of the static field when the VarHandle is created. As specified in the specification, the declaring class should be initialized when the VarHandle is operated on if it has not already been initialized. This issue is fixed in this release. The declaring class is no longer eagerly initialized when MethodHandles.Lookup::findStaticVarHandle is called. Existing code that relies on the previous behavior may observe a change of the order of the classes being initialized.

Gregorian era names with java.time.format APIs (JDK-8306116)


Names for Gregorian eras returned from java.time.format APIs are now correctly retrieved from the CLDR locale data. Prior to this change, these APIs incorrectly used names from the legacy COMPAT locale data. For example, the Gregorian era names "BCE"/"CE" are now returned for the ROOT locale, instead of "BC"/"AD" that are in the COMPAT locale data. For possible compatibility issues and workarounds, refer to JDK-8320431 for more details.

G1: More Deterministic Heap Resize at Remark (JDK-8314573)


During the Remark pause G1 adjusts the Java heap size to keep a minimum and maximum amount of free regions as set via the -XX:MinHeapFreeRatio and -XX:MaxHeapFreeRatio options.

Before this change, G1 considered Eden regions as occupied (full) for this calculation. This makes heap sizing very dependent on current Eden occupancy, although after the next garbage collection these regions will be empty. With this change, Eden regions are considered as empty (free) for matters of Java heap sizing. This new policy also aligns Java heap sizing to full GC heap sizing.

The effect is that G1 now expands the Java heap less aggressively and more deterministically, with corresponding memory savings but potentially executing more garbage collections.

The javac Compiler Should Not Accept Private Method References with a Type Variable Receiver (JDK-8318160)


Prior to JDK 22, the javac compiler was accepting private method references with a type variable receiver. This implies that the javac compiler was accepting code like:

import java.util.function.*;
class Test {
    private String asString() {
        return "bar";

    static <T extends Test> Function<T, String> foo() {
        return T::asString;

Starting from JDK 22 private method references with type variable receiver will be rejected by the javac compiler.

TypeMirror Changed to Provide Annotations for Types Loaded from Bytecode (JDK-8225377)


The implementation of TypeMirror now provides access to annotations for types loaded from bytecode. Previously type annotations were not associated with types loaded from bytecode.

Annotation processors can access type annotations for elements using AnnotationMirror#getAnnotationMirrors, and the annotations will be included in the output of AnnotationMirror#toString.

Any programs that relied on annotations being omitted for elements loaded from the classpath should be updated to handle type annotations.

ExecutableElement.getReceiverType and ExecutableType.getReceiverType() Changed to Return Annotated Receiver Types For Methods Loaded From Bytecode (JDK-8319196)


The implementation of ExecutableElement.getReceiverType and ExecutableType.getReceiverType now returns a receiver type for methods loaded from bytecode if the type has associated type annotations. Previously it returned NOTYPE for all methods loaded from bytecode, which prevented associated type annotations from being retrieved.

Known Issues

JFR: Increased Startup Time when Using -XX:StartFlightRecording (JDK-8319551)


A noticeable increase in startup time can be observed when using the -XX:StartFlightRecording option with smaller applications. This is due to an ongoing initiative to reduce technical debt in the JFR bytecode instrumentation. The work is anticipated to be finished in a future release, resulting in a startup time that is comparable to JDK 21.

Potential Performance Regression Due to Limited Range Check Elimination (JDK-8314468 (not public))


When the C1 compiler is the only compiler available to the VM, it applies loop predication to remove array access range checks from loop bodies. Due to a defect, this optimization was disabled, potentially leading to a performance regression.

This only affects the client VM or VM's running with the non-default command line flags -XX:+NeverActAsServerClassMachine or -XX:TieredStopAtLevel=[1,2,3].

JVM May Crash or Malfunction When Using ZGC and Non-Default ObjectAlignmentInBytes (JDK-8325074)


Running the JVM with -XX:+UseZGC and non-default value of -XX:ObjectAlignmentInBytes may lead to JVM crashes or incorrect execution.

Other Notes

Added Certigna Root CA Certificate (JDK-8314960)


The following root certificate has been added to the cacerts truststore:

+ Certigna (Dhimyotis)
  + certignarootca
    DN: CN=Certigna Root CA, OU=0002 48146308100036, O=Dhimyotis, C=FR

AWT SystemTray API Is Not Supported on Most Linux Desktops (JDK-8322750)


The java.awt.SystemTray API is used for notifications in a desktop taskbar and may include an icon representing an application. On Linux, the Gnome desktop's own icon support in the taskbar has not worked properly for several years due to a platform bug. This, in turn, has affected the JDK's API, which relies upon that.

Therefore, in accordance with the existing Java SE specification, java.awt.SystemTray.isSupported() will return false where ever the JDK determines the platform bug is likely to be present.

The impact of this is likely to be limited since applications always must check for that support anyway. Additionally, some distros have not supported the SystemTray for several years unless the end-user chooses to install non-bundled desktop extensions.

JFR Event for @Deprecated Methods (JDK-8211238)


A new JFR event, jdk.DeprecatedInvocation, has been added to JDK 22 to help users detect their use of deprecated methods located in the JDK.

To record these events in JFR, a user must specify a recording on the command line, like -XX:StartFlightRecording. Starting a recording during runtime, for example, using jcmd or the JFR Java API, will not have these events reported unless -XX:StartFlightRecording is specified on the command line.

An example event would be rendered like this using the JFR tool:

bin/jfr print <recording.jfr>

jdk.DeprecatedInvocation {
  startTime = 23:31:28.431 (2023-12-04)
  method = jdk.jfr.internal.test.DeprecatedThing.foo()
  invocationTime = 23:31:25.954 (2023-12-04)
  forRemoval = true
  stackTrace = [
    jdk.jfr.event.runtime.TestDeprecatedEvent.testLevelAll() line: 96

The current design will only report direct method invocations where the caller resides outside the JDK. Intra-JDK invocations will not be reported. Additionally, invoking methods declared deprecated but located outside of the JDK, for example in a third-party library, will not be reported, at least not during this first implementation. This might change in the future.

There exists a small restriction in the reporting of invocations from the Interpreter. In the situation where two caller methods are members of the same class, and they invoke the same deprecated method, for example:

public class InterpreterRestriction {
    public static void main(String[] args) {
    private static void invoke1() {
    private static void invoke2() {

In this situation, only <InterpreterRestriction.invoke1, System.getSecurityManager> will be reported because the Interpreter implementation will consider System.getSecurityManager() to be resolved and linked after the first call. When invoke2() is called, no slow path will be taken for the resolution of the System.getSecurityManager() method because it is already resolved as part of the cpCache. This restriction does not exist in C1 or C2, only in the Interpreter.

When analyzing the reported events, checking all methods in the reported class is recommended. This slight restriction can be resolved using an iterative process; if one call site is fixed, the other will be reported in the next run.

java.io.File Drops the Windows Long Path Prefix from Path Strings (JDK-8287843)


On Windows, java.io.File has changed in this release such that creating a File from a path string with a long path prefix (\\?\ or \\?\UNC) will now strip the prefix. This change fixes several anomalies with file path parsing, helps with interoperability with native code when the file path comes from a native program that includes the long path prefix, and also allows methods such as File::getCanonicalFile to return the canonical file from input that initially contained a long path prefix. The change to java.io.File aligns the behavior with the newer API java.nio.file.Path.

The change may be observable to code that depends on File::toString returning a String that has the long path prefix.

This change has no impact to file access, the JDK will continue to use the long path prefix when accessing files that need the prefix.

JLine As The Default Console Provider (JDK-8308591)


System.console() has changed in this release to return a Console with enhanced editing features that improve the experience of programs that use the Console API. In addition, System.console() now returns a Console object when the standard streams are redirected or connected to a virtual terminal. In prior releases, System.console() returned null for these cases. This change may impact code that uses the return from System.console() to test if the VM is connected to a terminal. If needed, running with -Djdk.console=java.base will restore older behavior where the console is only returned when it is connected to a terminal.

A new method Console.isTerminal() has been added to test if console is connected to a terminal.

Reimplement sun.reflect.ReflectionFactory::newConstructorForSerialization with Method Handles (JDK-8315810)


sun.reflect.ReflectionFactory::newConstructorForSerialization is reimplemented with method handles.

When newConstructorForSerialization(C.class, ctor) is called with a constructor whose declaring class is not a superclass of C, the old implementation returned an ill-formed constructor such that if newInstance is invoked, the behavior is unspecified. The new implementation will throw an UnsupportedOperationException instead, to fail fast.

Corrected ProxySelector Parameter Validation (JDK-8318150)


The java.net.ProxySelector methods select and connectFailure now throw IllegalArgumentException in all ProxySelector implementations when called with invalid parameters.

Previously, the select method of the ProxySelector returned by ProxySelector.of(InetSocketAddress) was incorrectly throwing a NullPointerException when its uri parameter was null or if the protocol could not be determined. The connectFailed method of the same ProxySelector instance returned without checking its parameters for validity.

Support for CLDR Version 44 (JDK-8306116)


The locale data based on the Unicode Consortium's CLDR has been upgraded to version 44. Besides the usual addition of new locale data and translation changes, there are two notable date/time format changes from the upstream CLDR:

  • Mexico and Latin American countries changed their time formats from 24 hours to 12 hours (CLDR-16358)
  • The FULL date format for Australia and the United Kingdom no longer has a comma after weekday (CLDR-16974)

Note that those locale data are subject to change in a future release of the CLDR, so users should not assume stability across releases. For more detailed locale data changes, please refer to the Unicode Consortium's CLDR release notes.

jdk.internal.vm.compiler Renamed to jdk.graal.compiler (JDK-8318027)


In preparation for Project Galahad, the jdk.internal.vm.compiler module was renamed to jdk.graal.compiler. Being a JDK internal module, this should be transparent for most Java users. However, scripts that run jlink to create a run-time image containing the Graal compiler module will need to be updated to use the new module name.

Exit VM for CompileCommand Parsing Errors (JDK-8282797)


-XX:CompileCommand=... will now exit the VM with a non-zero exit code after a parsing error occurs.

Unify Syntax of CompileOnly and CompileCommand (JDK-8027711)


-XX:CompileOnly=pattern1,[...],patternN is now an alias for -XX:CompileCommand=compileonly,pattern1 [...] -XX:CompileCommand=compileonly,patternN

Allow JIT Compilation for -Xshare:dump (JDK-8305753)


It is now possible to enable JIT compilation when creating a CDS archive with the -Xshare:dump JVM option. By default, when -Xshare:dump is specified, the JIT compiler is disabled, as if the -Xint option were specified. This is necessary for creating CDS archives with deterministic content (see JDK-8241071). However, when creating a CDS archive with a very large class list, and when deterministic content is not required, you can add the -Xmixed option along with -Xshare:dump to enable the JIT compiler, which will speed up the archive creation.

Hotspot hs_err Files Now Print the Lock Stack (JDK-8316735)


A section containing the thread local lock stack has been added to hs_err report files. It only gets printed when the new lightweight locking mode is enabled (-XX:LockingMode=2).

An example is given here with details about the locked objects omitted:

Lock stack of current Java thread (top to bottom):
LockStack[1]: nsk.share.jdi.EventHandler 
LockStack[0]: java.util.Collections$SynchronizedRandomAccessList

It lists objects which are lightweight locked, through synchronized methods or statements, by the Java thread which is being analyzed. The object which has been locked most recently is printed first. Objects which are not lightweight locked are not displayed in this section.

Add User Facing Warning If THPs Are Enabled but Cannot Be Used (JDK-8313782)


On Linux, if the JVM is started with +UseTransparentHugePages but the system does not support Transparent Huge Pages, a warning will now be printed to stdout:

UseTransparentHugePages disabled; transparent huge pages are not supported by the operating system.

NMT: Make Peak Values Available in Release Builds (JDK-8317772)


NMT reports will now show peak values for all categories. Peak values contain the highest value for committed memory in a given NMT category over the lifetime of the JVM process.

If the committed memory for an NMT category is currently at peak, NMT prints "at peak"; otherwise, it prints the peak value.

For example:

-                  Compiler (reserved=230KB, committed=230KB)
                            (malloc=34KB #64) (peak=49KB #71) 
                            (arena=196KB #4) (peak=6126KB #16)

This shows Compiler arena memory peaked at a bit more than 6MB, whereas it now hovers around 200 KB.

Add -XX:UserThreadWaitAttemptsAtExit=<number_of_waits> (JDK-8314243)


A new flag, -XX:UserThreadWaitAttemptsAtExit=<number_of_waits>, has been introduced. This flag is to specify the number of times the JVM waits for user threads to stop executing native code during a JVM exit. Each wait lasts 10 milliseconds. The maximum number of waits is 1000, to wait at most 10 seconds. By default, UserThreadWaitAttemptsAtExit is 30, thus the JVM may wait up to 300 milliseconds for user threads to stop executing native code when the JVM is exiting. That is the same as the existing behavior.

The Linux Specific Options UseSHM and UseHugeTLBFS Are Now Obsolete (JDK-8261894)


On Linux, if UseLargePages is enabled and UseTransparentHugePages is disabled, static or explicit large page mode, the options UseSHM and UseHugeTLBFS existed to switch between the two different implementations:

  • UseHugeTLBFS would cause the JVM to use POSIX APIs for allocating large pages.
  • UseSHM would let the JVM would use System V APIs. UseHugeTLBFS had been the default if both options were omitted.

The UseSHM mode offered no advantage over UseHugeTLBFS and has therefore been removed. The switch UseSHM has been obsoleted.

The JVM will now always use POSIX APIs for managing large pages. The switch UseHugeTLBFS has also been obsoleted; UseHugeTLBFS is now unconditionally enabled and cannot be switched off.

Two Phase Segmented Heap Dump (JDK-8306441)


During a heap dump, the application must pause execution and wait for the VM to complete the heap dump before resuming. This enhancement aims to minimize application pause time as much as possible by dividing the heap dump into two phases:

  • Phase one: Concurrent threads directly write data to segmented heap files. (Application is paused)
  • Phase two: Multiple heap files are merged into a complete heap dump file. (Application is resumed)

This approach significantly reduces application pause time, but it is important to note that the total time required for the heap dump itself remains unchanged. This optimization solely focuses on minimizing the impact on the application's pause time.

When executing jmap or jcmd GC.heap_dump, the VM automatically selects an appropriate number of parallel threads based on the type of garbage collector, number of processors, heap size, and degree of fragmentation. It will attempt to perform a parallel heap dump whenever possible, falling back to using a single thread when a parallel heap dump is not possible. In this case, the heap dump behavior is the same as before, and the details of the heap dump can be observed using the -Xlog:heapdump option.

Added Three Root Certificates from eMudhra Technologies Limited (JDK-8319187)


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

+ eMudhra Technologies Limited
  + emsignrootcag1
    DN: CN=emSign Root CA - G1, O=eMudhra Technologies Limited, OU=emSign PKI, C=IN

+ eMudhra Technologies Limited
  + emsigneccrootcag3
    DN: CN=emSign ECC Root CA - G3, O=eMudhra Technologies Limited, OU=emSign PKI, C=IN

+ eMudhra Technologies Limited
  + emsignrootcag2
    DN: CN=emSign Root CA - G2, O=eMudhra Technologies Limited, OU=emSign PKI, C=IN

Added Four Root Certificates from DigiCert, Inc. (JDK-8318759)


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

+ DigiCert, Inc.
  + digicertcseccrootg5
    DN: CN=CN=DigiCert CS ECC P384 Root G5, O="DigiCert, Inc.", C=US

+ DigiCert, Inc.
  + digicertcsrsarootg5
    DN: CN=DigiCert CS RSA4096 Root G5, O="DigiCert, Inc.", C=US

+ DigiCert, Inc.
  + digicerttlseccrootg5
    DN: DigiCert TLS ECC P384 Root G5, O="DigiCert, Inc.", C=US

+ DigiCert, Inc.
  + digicerttlsrsarootg5
    DN: DigiCert TLS RSA4096 Root G5, O="DigiCert, Inc.", C=US

Added ISRG Root X2 CA Certificate from Let's Encrypt (JDK-8317374)


The following root certificate has been added to the cacerts truststore:

+ Let's Encrypt
  + letsencryptisrgx2
    DN: CN=ISRG Root X2, O=Internet Security Research Group, C=US

Added Telia Root CA v2 Certificate (JDK-8317373)


The following root certificate has been added to the cacerts truststore:

+ Telia Root CA v2
  + teliarootcav2
    DN: CN=Telia Root CA v2, O=Telia Finland Oyj, C=FI

Increase Default Value of the System Property jdk.jar.maxSignatureFileSize (JDK-8312489)


The system property, jdk.jar.maxSignatureFileSize, allows applications to control the maximum size of signature files in a signed JAR. Its default value has been increased from 8000000 bytes (8 MB) to 16000000 bytes (16 MB).

KEM.getInstance() Should Check If a Third-Party Security Provider Is Signed (JDK-8322971)


When instantiating a third-party security provider's implementation (class) of a KEM algorithm, the framework will determine the provider's codebase (JAR file) and verify its signature. In this way, JCA authenticates the provider and ensures that only providers signed by a trusted entity can be plugged into the JCA. This is consistent with other JCE service classes, such as Cipher, Mac, KeyAgreement, and others.

Add Separate System Properties for TLS Server and Client for Maximum Chain Length (JDK-8311596)


Two new system properties, jdk.tls.server.maxInboundCertificateChainLength and jdk.tls.client.maxInboundCertificateChainLength, have been added to set the maximum allowed length of the certificate chain accepted from the client or server during TLS/DTLS handshaking.

A service can function as both a TLS/DTLS server and client. When the service acts as a server, it enforces a maximum certificate chain length accepted from clients. When the service acts as a client, it enforces a maximum certificate chain length accepted from servers.

These properties, if set, override the existing jdk.tls.maxCertificateChainLength system property. The properties work together as follows:

If the jdk.tls.server.maxInboundCertificateChainLength system property is set and its value is greater than or equal to 0, this value will be used to enforce the maximum length of a client certificate chain accepted by a server. Otherwise, if the jdk.tls.maxCertificateChainLength system property is set and its value is greater than or equal to 0, this value will be used to enforce it. If neither property is set, a default value of 8 will be used for enforcement.

If the jdk.tls.client.maxInboundCertificateChainLength system property is set and its value is greater than or equal to 0, this value will be used to enforce the maximum length of a server certificate chain accepted by a client. Otherwise, if the jdk.tls.maxCertificateChainLength system property is set and its value is greater than or equal to 0, this value will be used to enforce it. If neither property is set, a default value of 10 will be used for enforcement.

In this release, the default maximum chain length accepted from clients has been changed from 10 to 8 for client certificate chains.

Read Files in includedir in Alphanumeric Order (JDK-8309356)


JDK 10 added support for the includedir DIRNAME directive in krb5.conf. With this code change, files in this directory are read in alphanumeric order. Prior to this change, the files were read in no specific order. This is to be consistent with MIT krb5 1.17 (released on 2019-01-08).

Align javac with the Java Language Specification by Rejecting final in Record Patterns (JDK-8317300)


JDK 21 introduced pattern matching in the Java language. However, javac allowed final in front of a record pattern, such as (case final R(...) ->), something which is not allowed by the Java Language Specification.

Programs that could be compiled erroneously in JDK21 with final will now fail to compile. This change fixes the issue in the compiler. Impacted users will need to remove the final keyword.

When Using --release N, the System Module Descriptors Will Contain N As the Module Version (JDK-8318913)


For release builds of the JDK, when javac is used with --release N, the module descriptors for system modules will always contain N as their module version, regardless of the current JDK release and update release versions.

For pre-release builds of JDK, the version will contain the pre-release identifiers in addition to N.

Previously, the module version encoded in the module descriptors was either missing, for JDK release N, and --release M, where M < N, or the full module version, including update versions for JDK release N and --release N.

Add lint Warning for Restricted Method Calls (JDK-8316971)


Some methods in the Foreign Function & Memory API are unsafe. When used improperly, these methods can lead to loss of memory safety which can result in a JVM crash or silent memory corruption. Accordingly, the unsafe methods in the FFM API are restricted. This means that their use is permitted, but by default causes a warning to be issued at run time. To indicate where run time warnings may occur, a new javac lint option, -Xlint:restricted, causes warnings to be issued at compile time if restricted methods are called in source code. These compile-time warnings can be suppressed using @SuppressWarnings("restricted").

-XshowSettings Launcher Behavior Changes (JDK-8311653)


The -XshowSettings:all and -XshowSettings launch options now differ in behavior. -XshowSettings will print a summary view for the locale and security categories and all information for the other categories. -XshowSettings:all will continue to print all settings information available.

The -XshowSettings launcher option will now reject bad values passed to it. In such cases, an error message is printed and the JVM launch is aborted. See java -X for valid options that can be used with the -XshowSettings option.

Available Locales Information Now Listed with -XshowSettings:locale Option (JDK-8310201)


The showSettings launcher option no longer prints available locales information by default, when -XshowSettings is used. The -XshowSettings:locale option will continue to print all settings related to available locales.