G1GC
G1GC, as its name suggests, uses a Garbage First strategy.
This means it's a GC that controls the overall pause time by first collecting regions where many objects are concentrated.
To achieve this, G1 sets the following goals:
- Predictable Pause Time
- Divide the entire Heap into equally sized Regions
- Clearly distinguish Young/Old generations, but also allow Old areas to be collected in Region units
- Process Old areas based on Evacuation, including Compaction
- Avoid Full GC as much as possible, replacing it with Mixed Collection
In short, it's a region-based + incremental, evacuation-based Pause Time Control Collector.
evacuation: A GC operation that copies live objects to a new memory area and then discards the entire original area.
Meaning of Incremental: There are two meanings. One is to execute GC in multiple pieces, meaning it doesn't process the entire heap with STW at once, but rather performs small amounts of work repeatedly. The other is to perform evacuation incrementally. The core idea is to avoid batch processing and execute partially.
Region-Based Structure #
The core of G1GC is dividing the heap into fixed-size regions (typically 1 to 32MB).
Region Types #
- young region: eden/survivor
- old region
- humongous region: stores objects too large to fit in a single region (> 50% region size); essentially similar to old object handling, but more likely to trigger full GC.
G1GC tracks the live ratio of objects per region.
Major Structure: Young Collection, Mixed Collection #
G1GC has two main types of regular collections.
young collection (minor gc)
- Eden -> Survivor (Evacuate)
- Objects in Survivor are promoted to old if they survive.
- Since it's region-unit evacuation, compaction is always automatic.
- This means there is no fragmentation.
mixed gc
- Old regions are also collected by selecting only a few regions for evacuation, similar to young regions. This is how G1GC performs major GC without STW full compaction.
Mixed GC starts when a Marking Cycle ends.
Concurrent Marking Cycle (Old Collection Starting Point) #
This is the real core of G1.
The criterion for collecting old regions is an accurate Mark Bitmap indicating which objects are live.
The Marking Cycle consists of the following phases:
1. Initial Mark (STW)
2. Root Region Scan (Concurrent)
3. Concurrent Mark (Concurrent)
4. Remark (STW)
5. Cleanup (Concurrent + partial STW)

- Initial Mark: During a short STW period, similar to young GC, only the initial mark points are identified based on the root set. The pause is very short.
- Concurrent Mark: Simultaneously, the application runs while the GC traverses the old object graph and records it in the mark bitmap.
- Remark: Processes the SATB buffer to compensate for any missed marking. This is STW but highly optimized and short.
- Cleanup
- Calculate Live Ratio
- Register regions with low Live Ratio as candidates for Mixed GC.
- Most of this work is concurrent.
SATB (Snapshot-At-The-Beginning) Marking #
This is an important part of concurrent marking.
G1 attempts to determine live objects based on a heap snapshot taken at the start of the marking cycle. The problem is that object references continuously change during marking.
Therefore, a write barrier is used to track old references before they are changed.
SATB operation concept:
- If an object field changes to a different object during the marking cycle, the original object (
oldVal) that was in that field is put into the SATB buffer. - The reason is that the
oldValmight have been live when marking began.
In other words, G1GC tracks disappearing references, not new ones.
This is SATB, and its purpose is to maintain a heap snapshot at the moment marking begins.
Write Barrier Structure #
The G1GC write barrier includes both the SATB write barrier and Card Table Dirtying.
SATB Write Barrier
if (object.field ← new_ref) {
enqueue(old_ref) // old reference를 SATB queue에 넣음
}
Card Table Write Barrier: When an Old -> Young reference is created, the Card is marked Dirty for use in the later Remark phase.
Thus, the write barrier performs two purposes simultaneously:
1) Maintain SATB Snapshot (record old ref)
2) Update Remembered Set (Card Table dirty)
Remembered Set (RSet) #
To perform GC on a region-by-region basis, it's necessary to know about references coming from outside that region.
For this purpose, each region has a remembered set.
The RSet is a structure based on the Card Table that records who is referencing it, and it is a core structure that enables region-unit evacuation.
Evacuation #
G1 is mostly based on evacuation (emptying, moving to safety) unless it's a full GC.
Evacuation = moving live objects to a new region and immediately reclaiming the old region.
This process always involves compaction, so fragmentation essentially doesn't exist. This is a major difference from CMS.
Pause Time Control #
G1 selects regions with the lowest Live Ratio among several regions for Evacuation.
Since the cost of Evacuation is predictable, G1 determines how many regions to process in the current GC based on the Pause Time Goal.
Target Pause = 200ms
Evacuate one Region = 8ms
→ 200ms / 8ms = 25 Regions to Evacuate
-XX:MaxGCPauseMillis=<ms>
You can set the target pause time like this.
Humongous Region Handling #
Large objects can occupy multiple regions or a single humongous region.
Humongous objects are a cause of fragmentation and are difficult to remove with mixed GC, making them a primary trigger for full GC.
Full GC fallback #
Even G1 can experience full GC.
- When there are too many humongous regions and they are inefficient.
- Evacuation failure (insufficient new regions).
- RSet size explosion.
- SATB queue overflow.
- Insufficient Native Memory.
- When the Old Region Live Ratio remains high, making Mixed GC ineffective.
G1 full GC uses a STW compacting algorithm similar to the traditional serial full GC.
Summary of STW Points #
Among all phases of G1GC, STW occurs only at the following points:
- Initial Mark
- Remark
- Evacuation (collection)
- Partial Cleanup
- Entire Full GC
Most other operations are concurrent.
G1GC Chronic Cost Points #
The following factors actually determine G1 performance:
- Remembered Set Maintenance cost
- Write Barrier overhead (SATB + Card Table)
- Evacuation bandwidth
- Decreased effectiveness of Mixed GC (Old regions are too live)
- Proportion of Humongous objects
Due to these costs, the following JVM options are often tuned:
-XX:G1HeapRegionSize
-XX:MaxGCPauseMillis
-XX:G1NewSizePercent, -XX:G1MaxNewSizePercent
-XX:G1ReservePercent
-XX:G1HeapWastePercent
-XX:+UseStringDeduplication
Flowchart
[Repeat Young GC]
-> Eden/Survivor Evacuation
[Old area increases → Concurrent Marking Cycle starts]
1) Initial Mark (STW, very short)
2) Concurrent Mark (SATB-based)
3) Final Remark (STW)
4) Cleanup (Mostly Concurrent)
5) Register Old Regions with low Live Ratio as collection candidates
[Repeat Mixed GC]
-> Young + partial Old Region Evacuation
[Data compression + Region reuse]
[Possible Full GC fallback]