G1GC is mainly designed for one thing, keeping your application responsive by:

trying to avoid that garbage collection of the "old gen" (the tenured objects that the application has hold on to for some time, like from a user session, cache, or some kind of memory leak) must be done in a single classic FullGC where your application is frozen while the entire heap has to be cleaned (which depending on the number of objects may take a long time, like several seconds. Read all about it here, one quote from it:

The goal is to reclaim as much heap space as possible (starting with those regions that contain the most reclaimable space) while attempting to not exceed the pause time goal

The 40% you set for the: InitiatingHeapOccupancyPercent relate to the (entire) heap occupancy and denote when to start a concurrent GC cycle (this should be visible in the logs, if not see: this related question ). GCs that trigger a concurrent GC cycle based on the occupancy of the entire heap and not just one of the generations (so not just Old Gen), including G1, use this option. A value of 0 denotes 'do constant GC cycles'. The default value is 45. (Adapted from: Oracle® Communications WebRTC Session Controller System Administrator's Guide )

So it is possible that:

  1. The GC cycle is initiated at 40% heap occupancy but before it is finished you reach a much higher level (like 90%), which may be entirely fine as long as your application is working
  2. You have some kind of memory leak (but that is hard to tell from the graph without knowing the application and how long it is running or see how it plays out after a longer time)
  3. There may be some other problems but it is impossible to tell without having the garbage collection logs to analyse, but you may want to refer to: Monica Beckwith's article on G1GC e.g. the part on Evacuation Failure

If you really want your application to use less memory (maybe at the price of some loss in performance/throughput) you could lower the MaxHeapSize (but you should use either one of: MaxRAMFraction or MaxHeapSize (XmX), not both).

Or depending on your application and performance requirements consider going for an entirely different JVM/Garbage Collector like:

  • IBM/Eclipse OpenJ9 (see: https://developer.ibm.com/articles/garbage-collection-tradeoffs-and-tuning-with-openj9/ which is touted as having a very low memory overhead)
  • or any other GC mentioned in this research on Java memory elasticity discussing Shenandoah, ZGC, C4 and many others
Answer from JohannesB on Stack Overflow
Top answer
1 of 1
4

G1GC is mainly designed for one thing, keeping your application responsive by:

trying to avoid that garbage collection of the "old gen" (the tenured objects that the application has hold on to for some time, like from a user session, cache, or some kind of memory leak) must be done in a single classic FullGC where your application is frozen while the entire heap has to be cleaned (which depending on the number of objects may take a long time, like several seconds. Read all about it here, one quote from it:

The goal is to reclaim as much heap space as possible (starting with those regions that contain the most reclaimable space) while attempting to not exceed the pause time goal

The 40% you set for the: InitiatingHeapOccupancyPercent relate to the (entire) heap occupancy and denote when to start a concurrent GC cycle (this should be visible in the logs, if not see: this related question ). GCs that trigger a concurrent GC cycle based on the occupancy of the entire heap and not just one of the generations (so not just Old Gen), including G1, use this option. A value of 0 denotes 'do constant GC cycles'. The default value is 45. (Adapted from: Oracle® Communications WebRTC Session Controller System Administrator's Guide )

So it is possible that:

  1. The GC cycle is initiated at 40% heap occupancy but before it is finished you reach a much higher level (like 90%), which may be entirely fine as long as your application is working
  2. You have some kind of memory leak (but that is hard to tell from the graph without knowing the application and how long it is running or see how it plays out after a longer time)
  3. There may be some other problems but it is impossible to tell without having the garbage collection logs to analyse, but you may want to refer to: Monica Beckwith's article on G1GC e.g. the part on Evacuation Failure

If you really want your application to use less memory (maybe at the price of some loss in performance/throughput) you could lower the MaxHeapSize (but you should use either one of: MaxRAMFraction or MaxHeapSize (XmX), not both).

Or depending on your application and performance requirements consider going for an entirely different JVM/Garbage Collector like:

  • IBM/Eclipse OpenJ9 (see: https://developer.ibm.com/articles/garbage-collection-tradeoffs-and-tuning-with-openj9/ which is touted as having a very low memory overhead)
  • or any other GC mentioned in this research on Java memory elasticity discussing Shenandoah, ZGC, C4 and many others
🌐
Oracle
docs.oracle.com › en › java › javase › 21 › gctuning › garbage-first-g1-garbage-collector1.html
HotSpot Virtual Machine Garbage Collection Tuning Guide
October 20, 2025 - If this feature is active, then the option -XX:InitiatingHeapOccupancyPercent determines the initial value as a percentage of the size of the current old generation as long as there aren't enough observations to make a good prediction of the Initiating Heap Occupancy threshold.
🌐
Medium
medium.com › @hoan.nguyen.it › how-did-g1gc-tuning-flags-affect-our-back-end-web-app-c121d38dfe56
How Garbage First Garbage Collector (G1GC) affected the performance of our back-end | by Hoan Nguyen | Medium
August 9, 2024 - JDK8: We value low latencies and a seamless user experience, so we use G1GC. The G1GC flags were previously used, and they are still in use: -Xms10G -Xmx10G -XX:+UseG1GC -XX:+UseStringDeduplication -XX:G1NewSizePercent=30 -XX:InitiatingHeapOccupancyPercent=70
🌐
Krzysztofslusarski
krzysztofslusarski.github.io › 2021 › 08 › 16 › monday-mixed.html
[Java][JVM Logs][GC Logs][G1GC] Monday with JVM logs - efficiency of the old generation cleanup | JVM/Java profiling and tuning
August 16, 2021 - In this case, the value of -XX:InitiatingHeapOccupancyPercent always determines this threshold. Internally, Adaptive IHOP tries to set the Initiating Heap Occupancy so that the first mixed garbage collection of the space-reclamation phase starts when the old generation occupancy is at a current ...
🌐
HubSpot
product.hubspot.com › blog › g1gc-fundamentals-lessons-from-taming-garbage-collection
G1GC Fundamentals: Lessons from Taming Garbage Collection
April 14, 2016 - A Minor event is in progress, the Eden/From spaces have been emptied and resized and the application threads are still stopped. At this point, G1GC will make a check to determine if the MPCMC should be kicked off or not: 100(Heap currently used Total available heap) > -XX:InitiatingHeapOccupancyPercent
🌐
Heaphero
blog.heaphero.io › home › mastering g1gc: performance tuning for highthroughput and predictable latency in java
Mastering G1GC: Performance Tuning for HighThroughput and Predictable Latency in Java
March 31, 2026 - Give G1 enough heap: G1 needs room to work. Starving it of heap leads to more frequent GC and eventual Full GC. The -XX:InitiatingHeapOccupancyPercent (IHOP) flag controls when G1GC kicks off its concurrent marking cycle.
🌐
GC easy
blog.gceasy.io › home › simple & effective java g1 gc tuning tips
Simple & effective Java G1 GC tuning tips - GC easy - Universal Java GC Log Analyser
March 30, 2026 - Start the marking cycle earlier by reducing the ‘-XX:InitiatingHeapOccupancyPercent’. The default value is 45. Reducing the value will start the marking cycle earlier.
Find elsewhere
🌐
Medium
fnote.medium.com › g1gc-tuning-ec78d40861d
G1GC tuning. What is G1GC ? | by F Notes | Medium
December 26, 2019 - -XX:+UseG1GC disabled enableduse ... versus at incrementally at runtime -XX:InitiatingHeapOccupancyPercent45%%start marking when heap is...
🌐
Oracle
docs.oracle.com › javase › 8 › docs › technotes › guides › vm › gctuning › g1_gc.html
9 Garbage-First Garbage Collector
April 21, 2026 - Set the value of this parameter with the command-line option -XX:InitiatingHeapOccupancyPercent=<NN>. The default value of InitiatingHeapOccupancyPercent is 45.
🌐
Oracle
oracle.com › java › technical details
Garbage First Garbage Collector Tuning
Start the marking cycle earlier by reducing the -XX:InitiatingHeapOccupancyPercent.
🌐
Super User
superuser.com › questions › 1497068 › how-does-ihop-calculated-in-g1-gc-for-starting-concurrent-marking-cycle
java - How does IHOP calculated in G1 GC for starting concurrent marking cycle? - Super User
October 29, 2019 - -XX:InitiatingHeapOccupancyPercent=percent Sets the percentage of the heap occupancy (0 to 100) at which to start a concurrent GC cycle.
🌐
Oracle
docs.oracle.com › javase › 8 › docs › technotes › guides › vm › gctuning › g1_gc_tuning.html
10 Garbage-First Garbage Collector Tuning
April 21, 2026 - Start the marking cycle earlier by reducing the value of -XX:InitiatingHeapOccupancyPercent.
🌐
Elastic
discuss.elastic.co › elastic stack › elasticsearch
InitiatingHeapOccupancyPercent tuning parameter value modification ( 75 to 30 )from 7.0.1 version to 7.8.0 in G1GC for elasticsearch - Elasticsearch - Discuss the Elastic Stack
August 20, 2020 - 7.0.1 version's jvm.options snippet: ## G1GC Configuration # NOTE: G1GC is only supported on JDK version 10 or later. # To use G1GC uncomment the lines below. # 10-:-XX:-UseConcMarkSweepGC # 10-:-XX:-UseCMSInitiatingOccupancyOnly # 10-:-XX:+UseG1GC # 10-:-XX:InitiatingHeapOccupancyPercent=75 7.8.0 ...
Top answer
1 of 1
16

JDK-6976060 suggests that the need for a marking cycle is calculated at the end of a young GC. Depending on whether it uses the occupancy stats before or after the young GC this may or may not mean that eden space is always considered as 0% occupied for the purpose of IHOP calculation. With a 45% eden size that would mean 70% occupancy could never be reached, the maximum possible occupancy would be 55% and at that point the heap would be completely full and it would be too late for a mixed collection.

But I am doubtful whether this is truly the case because in the face of dynamic young generation sizing this would make the documentation misleading and IHOP tuning far more difficult. It should be fairly easy to verify this with an artificial test-case and manually sized generations.

If that's not the issue then GC pause (GCLocker Initiated GC) (young) might point to bug 8140597, which is fixed in jdk9b94.


Update: The description in Bug 8151176 indeed suggests that for the purpose of the IHO-percentage calculation it calculates oldgen occupancy/overall heap size. Which means young generation occupancy is completely ignored, which in turn means if young gen fraction > IHOP then it can never initiate a concurrent cycle.

The reason is that static IHOP starts if old gen occupancy exceeds a fixed percentage of the current heap capacity. If either the user or ergonomics decide that the old gen can not be larger than that fraction of the heap capacity that triggers concurrent mark, marking will never start.

So currently available solutions are

  • constrain the young gen fraction < IHOP
  • decrease IHOP to take the minimum possible old gen fraction into account
  • let the JVM adjust the IHOP dynamically

Update2: The latest comment on that bug indicates that this has been fixed for some time, so this answer should be considered as historic.

🌐
Medium
medium.com › @kaustubh.saha › g1-gc-8703990c2691
G1 GC. Garbage Collection (GC) is one of the… | by Kaustubh Saha | Medium
October 5, 2025 - -XX:initiatingHeapOccupancyPercent=45 ## default value - This means that by default, the G1 collector will attempt to start a concurrent marking cycle when the overall Java heap is 45% full.
🌐
Cloudera Community
community.cloudera.com › t5 › Support-Questions › How-should-I-set-InitiatingHeapOccupancyPercent-of-G1GC-for › m-p › 180782
How should I set InitiatingHeapOccupancyPercent of G1GC for NameNode with high usage of jvm heap
September 8, 2017 - Now I are trying to change GC from CMS to G1GC. And let's say, current situation of NameNode with CMS are Physical memory size : 140 GB -Xmx100G -Xms100G current actual heap usage : 70 - 80 GB (So, usage is around 80%.) -XX:InitiatingHeapOccupancyPercent : 90 The default value of "-XX:InitiatingHeap...
🌐
Medium
medium.com › @byterockai › how-g1-garbage-collector-work-in-java-e468a94ebed6
How G1 Garbage Collector work in Java | by ByteRock | Medium
March 20, 2025 - Default Value: Automatically calculated based on heap size. XX:InitiatingHeapOccupancyPercent · Description: Controls when G1GC starts its garbage collection cycle based on heap occupancy. Default Value: 45%. XX:ParallelGCThreads ·