JDK 11 G1 Adaptive IHOP Drops to a Very Low Percent After Humongous Allocations


Applies To

Java SE JDK and JRE - Version 11 through 15
Information in this document applies to any platform.


Symptoms

The JDK 11 Initiating Heap Occupancy Percentage (IHOP) is adaptive and set to 45%, by default. Note occupancy: ... threshold: ... (45.00) in the following GC log entry:

[2021-03-29T17:16:38.404-0700][11271.118s][3710][debug][gc,ergo,ihop ] Request concurrent cycle initiation (occupancy higher than threshold) occupancy: 5783945216B allocation request:5861520B threshold: 3865470566B (45.00) source: concurrent humongous allocation

After some humongous allocations, IHOP suddenly drops to a very low value, resulting in back-to-back concurrent collections. In the following GC log example, IHOP drops to 0.00% and stays there for a long time, resulting in back-to-back concurrent cycle requests:

[2021-03-29T17:35:38.384-0700][12411.098s][3710][debug][gc,ergo,ihop ] Request concurrent cycle initiation (occupancy higher than threshold) occupancy: 2399141888B allocation request:5861520B threshold: 0B (0.00) source: concurrent humongous allocation
[2021-03-29T17:35:38.496-0700][12411.210s][3710][debug][gc,ergo,ihop ] Request concurrent cycle initiation (occupancy higher than threshold) occupancy: 356515840B allocation request:3748752B threshold: 0B (0.00) source: concurrent humongous allocation
[2021-03-29T17:36:08.391-0700][12441.105s][3710][debug][gc,ergo,ihop ] Request concurrent cycle initiation (occupancy higher than threshold) occupancy: 377487360B allocation request:5861520B threshold: 0B (0.00) source: concurrent humongous allocation
[2021-03-29T17:36:08.498-0700][12441.212s][3710][debug][gc,ergo,ihop ] Request concurrent cycle initiation (occupancy higher than threshold) occupancy: 348127232B allocation request:3748752B threshold: 0B (0.00) source: concurrent humongous allocation

Young GCs have collected many of those humongous objects, but the IHOP does not change from the very low value.


Cause

This issue occurs when there are many short-lived humongous objects allocated on the heap, which are collected during Young collections. The adaptive IHOP calculation, by design, does not take into account objects that are collected by Young collections, even humongous objects.

After every Young-only garbage collection, G1’s Adative IHOP calculation is based on the old generation allocation rate (old_gen_allocated_bytes_since_last_gc / allocation_time_in_seconds). The value old_gen_allocated_bytes_since_last_gc consists of all allocations into old regions, including humongous regions. However, this does not account for the possibility that humongous objects can be reclaimed by Young GCs. This means that humongous allocations that have already been collected by a Young GC are still counted as allocated when IHOP is recalculated. For applications that allocate a lot of short-lived humongous objects, this can mean the old generation allocation rate is erroneously inflated, which in turn, keeps the IHOP lower than it should, resulting in back-to-back concurrent collections.

See JDK-8245511 - G1 adaptive IHOP does not account for reclamation of humongous objects by young GC for more information.


Solution

The solution is a JDK code enhancement that changes the IHOP calculation to account for reclamation of humongous objects by Young GCs. Behaviorally, this means that the IHOP may be lowered due to humongous allocations, but it will raise back up as short-lived humongous objects are reclaimed by Young GCs, thereby avoiding the multiple back-to-back concurrent collections.

This enhancement was first released in JDK 11.0.13, but it’s recommended to update to the latest JDK 11 release, which can be downloaded from Document 1414485.1 “Latest Java SE Patch Updates on MOS” or the Java Downloads page on Oracle.com. To implement the solution, please execute the following steps:

  1. Review the JDK 11 Consolidated Release Notes for any changes that may affect your application
  2. Download the JDK patch update (see links above)
  3. Ensure that you have made a backup of your system before applying the recommended patch update.
  4. Install the update in a test environment
  5. Confirm the following version with the command java -version.
  6. Retest the issue
  7. Migrate the solution as appropriate to other environments

Upgrading to JDK 17 or higher will also resolve this issue.

If unable to update the JDK at this time, a workaround is to disable adaptive IHOP with the following java command line flag:

    -XX:-G1UseAdaptiveIHOP

Last reviewed on Sat Feb 01 2025 00:00:00 GMT+0000 (Coordinated Universal Time)