To me, understanding what it really does, means to go the source code. I chose jdk-15.

The best description of this flag is here:

It determines the minimum reserve we should have in the heap to minimize the probability of promotion failure.

Excellent, so this has to do with "promotion failures" (whatever those are). But according to you quote in bold, this has something to do with AdaptiveIHOP also? Well yes, this parameter matters only in AdaptiveIHOP (which is on by default).

Another thing to notice is that G1ReservePercentage has no guarantee to be maintained all the time, it is a best effort.

If you look at how it is used in the very next line:

if (_free_regions_at_end_of_collection > _reserve_regions) {
    absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions;
}

things start to make some sense (for that bold statement). Notice how _reserve_regions are extracted for some computation. G1 will reserve that space for "promotion failures" (we will get to that).

If G1 reserves that space, it means less space is available for actual allocations. So if you "increase this buffer" (you make G1ReservePercent bigger as the quote suggests), your space for new objects becomes smaller and as such the time when GC needs to kick in will come sooner, so the time for when space reclamation needs to happen will come sooner too ("Lower the target occupancy for when to start space-reclamation..."). It is one complicated sentence, but in simple words it means that :

If you increase G1ReservePercentage, space will be needed to be reclaimed faster (more often GC calls).

Which, to be fair, is obvious. Not that I agree that you should increase that value, but this is what that sentence says.


After a certain GC cycle, be that minor, mixed or major, G1 knows how many regions are free:

_free_regions_at_end_of_collection = _g1h->num_free_regions();

Which of course, is the length of "free list":

return _free_list.length();

Based on this value and _reserve_regions (G1ReservePercent) plus the target pause time (200 ms by default) it can compute how many regions it needs for the next cycle. By the time next cycle ends, there might be a case when there are no empty regions (or the ones that are empty can not take all the live Objects that are supposed to be moved). Where is Eden supposed to move live Objects (Survivor), or, if old region is fragmented - where are live objects supposed to be moved to defragmente? This is what this buffer is for.

It acts as a safety-net (the comments in the code make this far more easier to understand). This is needed in the hopes that it will avoid a Full GC. Because if there are no free regions (or enough) to move live Objects a Full GC needs to happen (most probably followed by a young GC also).


This value is usually known to be small when this message is present in logs. Either increase it, or much better give more heap to the application.

Answer from Eugene on Stack Overflow
Top answer
1 of 1
8

To me, understanding what it really does, means to go the source code. I chose jdk-15.

The best description of this flag is here:

It determines the minimum reserve we should have in the heap to minimize the probability of promotion failure.

Excellent, so this has to do with "promotion failures" (whatever those are). But according to you quote in bold, this has something to do with AdaptiveIHOP also? Well yes, this parameter matters only in AdaptiveIHOP (which is on by default).

Another thing to notice is that G1ReservePercentage has no guarantee to be maintained all the time, it is a best effort.

If you look at how it is used in the very next line:

if (_free_regions_at_end_of_collection > _reserve_regions) {
    absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions;
}

things start to make some sense (for that bold statement). Notice how _reserve_regions are extracted for some computation. G1 will reserve that space for "promotion failures" (we will get to that).

If G1 reserves that space, it means less space is available for actual allocations. So if you "increase this buffer" (you make G1ReservePercent bigger as the quote suggests), your space for new objects becomes smaller and as such the time when GC needs to kick in will come sooner, so the time for when space reclamation needs to happen will come sooner too ("Lower the target occupancy for when to start space-reclamation..."). It is one complicated sentence, but in simple words it means that :

If you increase G1ReservePercentage, space will be needed to be reclaimed faster (more often GC calls).

Which, to be fair, is obvious. Not that I agree that you should increase that value, but this is what that sentence says.


After a certain GC cycle, be that minor, mixed or major, G1 knows how many regions are free:

_free_regions_at_end_of_collection = _g1h->num_free_regions();

Which of course, is the length of "free list":

return _free_list.length();

Based on this value and _reserve_regions (G1ReservePercent) plus the target pause time (200 ms by default) it can compute how many regions it needs for the next cycle. By the time next cycle ends, there might be a case when there are no empty regions (or the ones that are empty can not take all the live Objects that are supposed to be moved). Where is Eden supposed to move live Objects (Survivor), or, if old region is fragmented - where are live objects supposed to be moved to defragmente? This is what this buffer is for.

It acts as a safety-net (the comments in the code make this far more easier to understand). This is needed in the hopes that it will avoid a Full GC. Because if there are no free regions (or enough) to move live Objects a Full GC needs to happen (most probably followed by a young GC also).


This value is usually known to be small when this message is present in logs. Either increase it, or much better give more heap to the application.

🌐
Oracle
docs.oracle.com › javase › 8 › docs › technotes › guides › vm › gctuning › g1_gc_tuning.html
Garbage-First Garbage Collector Tuning
April 21, 2026 - Increase the value of the -XX:G1ReservePercent option (and the total heap accordingly) to increase the amount of reserve memory for "to-space".
Discussions

Garbage collection woes
I would split things up in to more shards. You're using 50 64GB instances for only 50TB of data, you shouldn't be having any issues with that at all, that's way overpowered (unless you're having CPU issues, I don't know much about GCP compute). We're doing 10 times that amount of storage per ECE deployment with maybe 100 64GB instances. You should have plenty of power to deal with the data and queries that you have. I wouldn't mess with the JVM settings yet. Certainly I wouldn't go beyond 32GB heap. Yes, I would increase the shard count, btw you can have a lot more than 20 shards per GB of heap. Look at your circuit breaker settings, look at query timeout settings. What's your actual index size? Very important for query performance. Adding a replica would usually also help, again you've got plenty of compute there to add a replica. And, possibly most importantly, audit the queries. You need to set up slowlog ( https://www.elastic.co/guide/en/elasticsearch/reference/7.17/index-modules-slowlog.html ) and see if people are running terrible queries that are knocking over your stack. More on reddit.com
🌐 r/elasticsearch
12
6
May 19, 2023
Garbage Collection is running, but it’s running extremely slow
java -Xms128M -Xmx6656M -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 ... More on answeroverflow.com
🌐 answeroverflow.com
July 19, 2023
Insuffecient memory when running hira, confluence and bit.
Get answers about Jira and other Atlassian products, connect with experts and our product teams, and get inspired by users just like you! More on community.atlassian.com
🌐 community.atlassian.com
April 3, 2018
Memory leak in all servers on pterodactyl 1.11.7
GC log attached and here are my ... -Daikars.new.flags=true -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -jar server.jar --nogui``` I've allocated 10GB of RAM just to keep it from crashing.... More on answeroverflow.com
🌐 answeroverflow.com
September 1, 2024
🌐
ycrash Answers
answers.ycrash.io › question › what-is-g1-garbage-collector-tuning--xxg1reservepercent
What is G1 garbage collector tuning: -XX:G1ReservePercent? - yCrash Answers
October 28, 2022 - -XX: G1ReservePercent=percent, where percent is desired percent of the heap from 0 to 50 that's reserved as a false ceiling.
🌐
Red Hat
redhat.com › en › blog › part-1-introduction-g1-garbage-collector
Part 1: Introduction to the G1 Garbage Collector
November 21, 2025 - G1 has an explicit hard-margin, defined by the G1ReservePercent (default 10%), that results in a percentage of the heap always being available for the Survivor space during evacuation.
🌐
Gceasy
gceasy.io › gc-recommendations › important-g1-gc-arguments.jsp
Important G1 GC Arguments
For tuning purposes, in the below table, we have summarized important G1 GC algorithm arguments and their default values: · GCeasy is the industry's first online Garbage collection log analysis tool aided by Machine Learning
🌐
Atlassian
jira.atlassian.com › browse › CONF-43493
Loading...
-XX:G1ReservePercent=20 · To-space allocation failures are very very slow, due to some bugs in the JDK which have been fixed in Java 9. We need to avoid these collections where possible. To briefly explain what this param does - G1GC splits the heap into regions and allocates those regions to Eden, Survivor and Tenured.
🌐
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 - XX:G1ReservePercent · Description: Reserves a percentage of heap memory for GC overhead. Default Value: 10% of the heap. XX:G1HeapWastePercent · Description: Controls the percentage of memory that can be wasted in a region before G1 considers ...
🌐
Oracle
docs.oracle.com › en › java › javase › 25 › gctuning › garbage-first-g1-garbage-collector1.html
HotSpot Virtual Machine Garbage Collection Tuning Guide
October 20, 2025 - This section describes the Garbage-First (G1) Garbage Collector (GC) · The Garbage-First (G1) garbage collector is targeted for multiprocessor machines scaling to a large amount of memory. It attempts to meet garbage collection pause-time goals with high probability while achieving high throughput ...
Find elsewhere
🌐
HubSpot
product.hubspot.com › blog › g1gc-fundamentals-lessons-from-taming-garbage-collection
G1GC Fundamentals: Lessons from Taming Garbage Collection
Tenured generally sits around 15%, IHOP is set to 30%, the Eden range is the default 5-60%. A G1ReservePercent of 15% is considered safe as occasionally 5% of the Free space is occupied through To-space overflow.
🌐
Reddit
reddit.com › r/elasticsearch › garbage collection woes
r/elasticsearch on Reddit: Garbage collection woes
May 19, 2023 -

I have a 7.17 cluster that is having severe problems with search and I could really use some advice. It's fairly search heavy, usually 3000-5000 per/sec. The data nodes will start going into frequent GC (young) and soon after I'll start getting search rejections and the downstream clients start breaking.

It's holding 50.5TB (1:1), 26 billion docs across 50 data nodes. The shards are between 35-45GB and each node holds about 30 shards.

The specs on the nodes are N2-himem-8 (we're running on VMs in GCP) which gives me 64GB RAM. The heap is set to 31GB and we're using G1GC garbage collection with the default JVM settings which means GC kicks in at about 23GB usage. The o/s is linux.

I think I've got 3 options, any advice would be appreciated.

  1. split the indices and reduce the shard size to 15-20GB, I know there's an overhead to shard management, 20 shards per GB of heap. It's counterintuitive but I've good reason to believe this could help.

  2. Tweak the JVM settings. I don't think ConcMarkSweep is recommended for larger heap sizes, so that basically leaves me with reducing the G1ReservePercent to 5 or 10. What are the implications of this ?

  3. Increase the heap beyond 31GB and bump up the platforms RAM

I know compressed memory pointers in a JVM aren't effective in larger heaps, *but* I thought that only applied to 32bit JVMs, and we're running 64bit JVMs. Am I wrong ?

Does anybody run elasticsearch with heaps larger than 31GB ?

🌐
Answer Overflow
answeroverflow.com › m › 1131304105919393903
Garbage Collection is running, but it's running extremely slow
July 19, 2023 - java -Xms128M -Xmx6656M -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 ...
🌐
OpenJDK
bugs.openjdk.org › browse › JDK-8257774
Loading...
These GCs are extremely long and result in 0 objects being evacuated. The situation is happening because of bursts of short lived humongous object allocations. These bursts quickly consume all of the G1ReservePercent regions and then the rest of the free regions.
🌐
Ycrash
ycrash.io › yc-load-report-gc
Brilliant GC graphs, metrics and KPIs
4. You can also increase the value of the '-XX:ConcGCThreads' argument to increase the number of parallel marking threads. Increasing the concurrent marking threads will make garbage collection run fast. 5. Increase the value of the '-XX:G1ReservePercent' argument.
🌐
Apache
jmeter.apache.org › usermanual › get-started.html
Apache JMeter - User's Manual: Getting Started
Java runtime options to specify JVM garbage collection algorithm. Defaults to -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:G1ReservePercent=20
🌐
X
x.com › TeltiaAditya › status › 1988290635971875315
Aditya Teltia on X: "proof that small changes unlock massive stability debugged an elasticsearch oom crash without a heap dump? node tanked at 67.8gib out of 70g heap, slamming the 95% circuit breaker. es's manual G1GC trigger was a last-ditch fail. applied the 5 whys (by sakichi toyoda) to peel https://t.co/TPmAxwfxV7" / X
proof that small changes unlock massive stability debugged an elasticsearch oom crash without a heap dump? node tanked at 67.8gib out of 70g heap, slamming the 95% circuit breaker. es's manual G1GC trigger was a last-ditch fail. applied the 5 whys (by sakichi toyoda) to peel back layers: why oom? heap spiked. why spiked? gc too late. why late? reserves tight. why tight? default -XX:G1ReservePercent=10 not enough for our load.
🌐
Minecraft Wiki
minecraft.fandom.com › wiki › Tutorials › Setting_up_a_server
Tutorials/Setting up a server – Minecraft Wiki
The default GC on Java 9+ used by modern Minecraft is G1GC (Java 8 also has it, but it is off by default). The flags used by the official launcher -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M works reasonably well, though of course better flags (brucethemoose) exist.
🌐
OpenJDK
mail.openjdk.org › pipermail › hotspot-gc-use › 2016-October › 002521.html
G1-GC - Full GC [humongous allocation request failed]
[...] > > > If young gen size + old gen occupancy starts eating into area 1), > > G1 minimizes young gen to try to keep as much memory left for these > > "extraneous allocations" that G1ReservePercent indicates, in the > > hope that the IHOP is "soon" kicking in.
🌐
Atlassian Community
community.atlassian.com › forums › Jira-questions › Insuffecient-memory-when-running-hira-confluence-and-bit › qaa-p › 764014
Insuffecient memory when running hira, confluence and bit.
April 3, 2018 - Get answers about Jira and other Atlassian products, connect with experts and our product teams, and get inspired by users just like you!
🌐
Answer Overflow
answeroverflow.com › m › 1279245850358448191
Memory leak in all servers on pterodactyl 1.11.7 - Admincraft
September 1, 2024 - java -Xms7680M -Xmx7680M --add-modules=jdk.incubator.vector -XX:+UseG1GC -Xlog:gc*:file=gc.log:time,tags:filecount=5,filesize=10M -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -jar server.jar --nogui I've allocated 10GB of RAM just to keep it from crashing.
🌐
OpenSearch
forum.opensearch.org › t › increase-opensearch-node-heap-size › 17950
Increase Opensearch node heap size - OpenSearch - OpenSearch
February 20, 2024 - Versions (relevant - OpenSearch/Dashboard/Server OS/Browser): OpenSearch: 2.11.1 Dashboard: 2.11.1 Describe the issue: I have used opensearch project helm to install opensarch in kubernetes env (GitHub - opensearch-project/helm-charts: ☸ A community repository for Helm Charts of OpenSearch Project.). I have been trying to update the default heap size, dut did not had luck.