Understanding the G1 Garbage Collector: Structure, Advantages, and Tuning
This article explains the G1 garbage collector’s architecture, region types, pause‑time prediction model, memory allocation parameters, collection phases, and tuning considerations, providing code examples and practical insights to improve performance for Java developers.
G1 Structure
G1 abandons the traditional generational collection approach and treats the entire heap as a set of equally sized independent regions called Regions.
There are four types of Regions:
Free Region
Young Region (still divided into Eden and Survivor)
Old Region
Humongous Region for large objects
The size of each Region is configured with -XX:G1HeapRegionSize , ranging from 1 MB to 32 MB. With a default maximum of 2048 Regions, G1 can manage up to 64 GB of heap memory.
Objects larger than half a Region are placed in a Humongous Region; objects larger than a whole Region occupy consecutive Humongous Regions.
G1 Advantages
The primary goal of any GC is to reduce stop‑the‑world (STW) pauses. Older collectors like CMS have unpredictable pause times, whereas G1 offers a predictable pause‑time model.
By setting -XX:MaxGCPauseMillis (default 200 ms), G1 evaluates each Region’s reclaimed space and pause cost, then prioritizes Regions that give the highest value‑to‑cost ratio within the desired pause window.
The model relies on an exponential moving average (EMA). The following code shows how G1 predicts the next pause:
hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
double get_new_prediction(TruncatedSeq* seq) {
return MAX2(seq->davg() + sigma() * seq->dsd(),
seq->davg() * confidence_factor(seq->num()));
}In the formula, davg is the EMA, sigma is a coefficient (default 0.5), dsd is the EMA’s standard deviation, and confidence_factor inflates the prediction when sample size is small.
Based on this model, G1 attempts to meet the user‑specified pause target by selecting Regions that maximize reclaimed space within the allowed time.
Space Allocation & Expansion
G1 still distinguishes young and old generations. Two parameters control young‑generation size:
G1MaxNewSizePercent
G1NewSizePercent
By default, G1NewSizePercent is 5 % of the heap and G1MaxNewSizePercent is 60 %.
For a 4 GB heap with the default 2048 Regions, each Region is 2 MB. The initial young generation occupies about 200 MB (≈100 Regions) and can expand up to 2.4 GB.
Heap size is set with -Xms (initial) and -Xmx (maximum). Young‑generation size can also be influenced by -Xmn , -XX:NewRatio , and -XX:SurvivorRatio according to the rules described.
The expansion trigger is -XX:GCTimeRatio (default 9). When GC time exceeds 10 % of application time, the heap expands by 20 % (minimum 1 MB).
Collection Process
G1 performs four main steps:
Initial Mark (STW) – marks objects reachable from GC roots.
Concurrent Mark – traverses the object graph concurrently, then revisits changes.
Final Mark (STW) – a short pause to catch any remaining updates.
Pause for Evacuation – selects Regions based on the pause‑time model, copies live objects to empty Regions, and clears the reclaimed Regions (STW).
Two types of GC cycles exist:
Young‑generation GC (YGC) – triggered when young Regions exceed a size threshold, using the classic copying algorithm.
Mixed GC – similar to Full GC; it collects both young and old Regions and Humongous Regions when heap occupancy reaches -XX:InitiatingHeapOccupancyPercent (default 45 %).
Other Topics
G1 uses a Remembered Set for each Region to track cross‑region references, stored as a hash table mapping source Region addresses to Card Table indices. Maintaining this set consumes about 10‑20 % of heap memory and relies on write barriers.
For concurrent marking, G1 employs the Snapshot‑At‑The‑Begin (SATB) algorithm to avoid interference between mutator and collector threads.
Summary
G1 replaces traditional generational collectors with a region‑based design, offering predictable pause times, flexible space allocation, and sophisticated reference tracking. Understanding its structure, pause‑time model, allocation parameters, and collection phases helps Java developers tune performance and avoid unexpected pauses.
Wukong Talks Architecture
Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.