Java 26 for DevOps

With every release of Java comes updates to the underlying runtime, and how JVM applications can be administered and observed. In this article we will review changes to this area that are coming Java 26, which is scheduled for release on March 17th.

Ahead-of-Time Computation for ZGC Users

JEP 516 Ahead-of-Time (AOT) Object Caching with Any GC, brings the benefits of AOT introduced in Java 24 (JEP 483) and 25 (JEPs 514 & 515), to Z Garbage Collector (ZGC) users. AOT improves the startup and warm up performance of Java applications, by storing information from a previous run of an application in a cache that can be accessed on subsequent runs. To learn more about AOT, watch my video on this subject.

JEP 516

G1 Garbage Collector Updates

G1, Java’s default garbage collector, remains under active development, and there are several notable changes coming in Java 26.

G1 GC: Improve Throughput by Reducing Synchronization

The throughput of the G1 garbage collector has been improved in Java 26 by reducing the frequency of synchronization with application threads. This was done by introducing a second card table allowing the optimizer and application threads to run freely. This also had the second order effect of reducing the write barriers in G1 from 50 intructions to 12.

Testing has shown that these changes have improved throughput by 5-15% percent, with applications that do heavy modification to object-reference fields seeing the most benefit. Additionally this new design is more efficent that the previous auxillry data structure, which resulted in a slight descrease in pause times. Lastly the second card table can in some cases slightly reduce memory overhead; each card table requiring about 2MB of native meory per 1GB of heap capacity. In cases where it does consume more memory than before, the difference is trivial.

JEP 522

Humongous Object Reclamation

The G1 garbage collector now eagerly reclaims eligible humongous objects (objects occupying more than half a heap region) containing references.

This change allows for the prompt recovery of memory previously held by such objects, particularly if they are short-lived, improving garbage collection efficiency and reducing heap usage. Previously such humongous objects were only reclaimed during full gcs.

This change applies to both discrete humongous objects, as well as to humongous arrays of references (i.e. Object[]).

JDK-8048180

G1 Overhead Limit

The G1 garbage collector now throws an OutOfMemoryException when the garbage collection overhead is more than the GCTimeLimit percent (default 98) and the free Java heap is less than the GCHeapFreeLimit percent (default 2) for five consecutive garbage collections. This can help prevent GC thrashing in such scenarios and mirrors the behavior implemented in the Parallel GC.

This feature is enabled by default. It can be disabled using the -XX:-UseGCOverheadLimit option.

JDK-8212084

Transparent Huge Pages Support

G1 can again properly utilize Transparent Huge Pages (THP) on systems with the THP mode configured as madvise, this resolves an issue introduced in Java 25. This issue has also been backported to 25.0.2.

JDK-8366434

JVM Flag Updates

There are a number of updates to JVM flags in Java 26.

InitialRAMPercentage Default Value Removed

InitialRAMPercentage is being changed from 1.5625 (1/64) to 0. The previous default value was last set in 2007. At that time, the value of 1.5625 was a reasonable assumption, but as available system memory has increased, it can result in excessively large heap sizes. This could result in wasted resources and slower startup performance.

To address this the default value of InitialRAMPercentage has been removed (set to 0), which matches with MinHeapSize and InitialHeapSize, which will default to using JVM ergonomics for setting these values. Users could, if needed, set these values using -Xms. It is also still possible to set InitialRAMPercentage explicitly; -XX: InitialRAMPercentage=[0.0-100].

JDK-8371986

Server and Client Flags Deprecated for Removal

The flags AlwaysActAsServerClassMachine and NeverActAsServerClassMachine are marked as deprecated for removal. The primary benefit of these flags was driving ergonomics for GC selection: G1 being used on server class machines, and Serial on client machines. However, with the future introduction of JEP 523, which makes G1 the default GC in all environments, there’s is little difference between the two JVM arguments.

JDK-8370843

AggressiveHeap Deprecated for Removal

The flag AggressiveHeap has been marked as deprecated for removal. AggressiveHeap was originally added to satisfy specific benchmarks, but lacks transparency. If your application depended on the behavior of AggressiveHeap, you can recreate it with the following set of flags:

-XX:+UseParallelGC -XX:+UseLargePages 
-XX:-ResizeTLAB -XX:TLABSize=256K 
-XX:YoungPLABSize=256K -XX:OldPLABSize=8K 
-XX:ThresholdTolerance=100

And additionally set the following flags to the relevant values based on your systems resources:

  • -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

JDK-8370813

MaxRAM Deprecated for Removal

The MaxRAM flag has been marked as deprecated for removal as the JVM can accurately detect physical RAM and set reasonable commit limits. Often times, users were setting other JVM flags: MaxRAMPercentage, MinRAMPercentage or InitialRAMPercentage as a means of getting around MaxRAM’s default of 128GB. Users should instead use -Xmx and -Xms for controlling heap size.

JDK-8369346

JMX Updates

JMX, Java Management Extensions, is a technology that can be used to provide a view in the a running JVM. There were a number of updates and changes to the JMX API in Java 26.

Garbage Collector CPU Usage

A new method getTotalGcCpuTime() has been added to java.lang.management.MemoryMXBean, which returns a long result with the accumulated CPU time in nanoseconds during the critical section and/or after JIT warmup.

JDK-8368527

Protocal Requires for JMXServiceURL

The class javax.management.remote.JMXServiceURL requires that a protocol is specified when using its String constructor. In prior releases when a null protocol was supplied to the constructor, the following exception was thrown:

java.net.MalformedURLException: Unsupported protocol: jmxmp
        at java.management/
        ...

This is inaccurate as jmxmp was a default value, but isn’t part of the JDK. This has been updated to not select jmxmp and instead print out the follow and more clear message:

java.net.MalformedURLException: Unsupported protocol: Misssing protocol name
        at java.management/
        ...

JDK-8347114

The classes javax.management.AttributeList, javax.management.relation.RoleList, and RoleUnresolvedList, have been updated to reject objects of the wrong type, as previous those objects were only verified when the asList() method was called.

JDK-8359809

MBeanServer Exception Change

The javax.management.MBeanServer:eregisterMBean() now throws a RuntimeOperationsException instead of NullPointerException when invoked with a null “object” parameter. This correction aligns the implementation with the specification.

JDK-8364227

Other Changes

There are a couple of other updates that don’t neatly fit into the above catagories.

C2 JIT Support Enhancement

The C2 JIT compiler can now compile Java methods with a large number of parameters (greater than 30). Previously, C2 would bail out when it attempted to compile such methods, causing the JVM to fall back to C1-compiled code or the interpreter.

JDK-8325467

Serial GC Eden Space

Prior to Java 26, the ordering of the young generation (YoungGen) in the Serial GC was eden follow by the to/from spaces (survivor regions). This meant that it was difficult for eden to expand to satisfy an allocation request, possibly resulting in a premature OutOfMemoryException (OOME).

With Java 26, eden has been moved to be after the to/from space, allowing it to possibly grow to the end of YoungGen to satisfy an allocation request. This might mean it grows beyond the limit governed by SurvivorRatio. However this behavior is desirable as it can avoid an OOME and VM termination.

JDK-8368740

Java 26 will be released on March 17th! If you are able to, be sure to attend JavaOne on March 17-19th, in Redwood Shores, California. A large part of the JDK Engineering team will be there, including some of the engineers who worked on the very issues covered in this article. It can be a great opportunity to learn about Java for the stewards of Java! For more check out https://javaone.com, hope you see you there!