Fundamentals 19 min read

Unlocking G1 GC: Why Your Java Service Hangs and How to Fix It

This article explains the G1 garbage collector’s heap layout, collection cycles, pause prediction, log analysis, and monitoring tools, helping Java developers diagnose and resolve performance issues such as frequent restarts, OOM, CPU spikes, and periodic latency spikes.

Ops Development Stories
Ops Development Stories
Ops Development Stories
Unlocking G1 GC: Why Your Java Service Hangs and How to Fix It

What does this article cover?

Heap layout (Region‑based: Eden, Survivor, Old, Humongous)

Garbage‑collection cycles

GC phases: initial mark, concurrent mark, final mark, evacuation

GC types: Minor, Full, Mixed

CSet (the set of Regions to collect in the young generation)

Cross‑generation references

Pause‑prediction model

GC log analysis

G1 Memory Heap Layout

G1 (Garbage‑First) is a generational collector that partitions the heap into Regions. The image below marks Humongous Regions (H) that store objects larger than half a Region.

G1 heap layout with Humongous regions
G1 heap layout with Humongous regions

Humongous objects are allocated directly in the old generation to avoid repeated copying.

They are reclaimed during the global concurrent marking cleanup and Full GC phases.

Before allocating a humongous object, G1 checks the Initiating Heap Occupancy Percent (IHOP) and the marking threshold; if exceeded, global concurrent marking starts to pre‑emptively reclaim space and avoid evacuation failures and Full GC.

GC Types

Young GC – collects young regions and humongous regions.

Mixed GC – collects young regions, old regions, and humongous regions.

Full GC – collects young, old, humongous regions, and Metaspace.

Collection Set (CSet)

The Collection Set is the group of Regions selected for collection in a given GC phase.

Young GC CSet: young regions + humongous regions.

Mixed GC CSet: young regions + old regions + humongous regions.

Cross‑Generation References

During Young GC, reachable objects are identified via GC roots. To avoid scanning the entire old generation for references to young objects, G1 records old‑to‑young references in a remembered set (RSet) implemented with a CardTable.

Cross‑generation reference diagram
Cross‑generation reference diagram

RSet (Remembered Set)

The RSet stores references from other Regions to a given Region, allowing the collector to locate live objects without scanning the whole heap. Each young Region maintains its own RSet, which can consume up to 20% of heap space.

CardTable

The old generation is divided into cards; each card records whether it contains references to the young generation. A value of 1 indicates a reference, which is then added to the RSet, improving the efficiency of cross‑generation reference queries.

Pause Prediction Model

G1 predicts pause times using variance‑based statistical models derived from historical data. (Reference: https://sdww2348115.github.io/jvm/g1/PausePredictionModel)

G1 GC Cycle

G1 GC cycle diagram
G1 GC cycle diagram

G1 alternates between two phases: Young‑only and Space Reclamation.

Young‑only: a series of operations that gradually promote long‑living objects to the old generation.

Space Reclamation: progressively reclaims space in the old generation while also handling young Regions.

When the old‑generation occupancy exceeds the InitiatingHeapOccupancyPercent (default 45%), G1 starts concurrent marking, which may take a long time but does not stop the application.

Blue circles: Young‑only pauses.

Yellow circles: Marking pauses.

Red circles: Mixed GC pauses.

GC Log Analysis

The following excerpt shows a series of G1 GC logs; each entry can be mapped to the phases described above.

[gc,start      ] GC(44265) Pause Young (Normal) (G1 Evacuation Pause)
[gc,task       ] GC(44265) Using 13 workers of 13 for evacuation
[gc,phases     ] GC(44265)   Pre Evacuate Collection Set: 0.1ms
[gc,phases     ] GC(44265)   Evacuate Collection Set: 101.8ms
[gc,phases     ] GC(44265)   Post Evacuate Collection Set: 3.2ms
[gc,phases     ] GC(44265)   Other: 2.7ms
[gc,heap       ] GC(44265) Eden regions: 1850->0(1851)
[gc,heap       ] GC(44265) Survivor regions: 70->69(240)
[gc,heap       ] GC(44265) Old regions: 766->768
[gc,heap       ] GC(44265) Humongous regions: 20->19
[gc,metaspace  ] GC(44265) Metaspace: 193280K->193280K(1230848K)
[gc            ] GC(44265) Pause Young (Normal) (G1 Evacuation Pause) 21642M->6843M(25600M) 107.561ms
[gc,cpu        ] GC(44265) User=1.31s Sys=0.00s Real=0.11s
... (additional log entries omitted for brevity) ...

Key observations:

GC(44265) is a normal Young GC showing region changes.

GC(44269) marks the start of the concurrent phase.

GC(44270) completes Cleanup, followed by Prepare Mixed GC (44271).

GC(44272) begins the Space Reclamation stage with multiple Mixed GCs.

Humongous objects are treated specially: G1 only decides their liveness and reclaims their space; they are never moved. During Young‑Only, humongous regions may be reclaimed. During Space Reclamation, humongous regions may be reclaimed.

JVM Performance Monitoring Tools

Useful tools for diagnosing JVM performance bottlenecks:

VisualVM

Glowroot

Arthas (https://arthas.aliyun.com/)

Thread‑dump analysis:

FastThread (https://fastthread.io/)

GC‑log analysis:

GCEasy (https://gceasy.io/gc-index.jsp)

Heap‑dump analysis:

IBM Heap Analyzer (https://www.ibm.com/support/pages/ibm-heapanalyzer)

Eclipse MAT (https://projects.eclipse.org/projects/tools.mat)

References

GC pause prediction model: http://www.narihiro.info/g1gc-impl-book/scheduling.html

GC pause prediction model: https://sdww2348115.github.io/jvm/g1/PausePredictionModel

Garbage collector execution process: https://bugs.openjdk.org/browse/JDK-8295118

Cross‑generation references: https://blog.csdn.net/weixin_47184173/article/details/113627337

Automatic heap memory return to OS: https://openjdk.org/jeps/346

Additional resources: https://docs.oracle.com/javacomponents/jmc-5-4/jfr-runtime-guide/comline.htm#JFRUH197, https://www.redhat.com/en/blog/part-1-introduction-g1-garbage-collector, https://blog.csdn.net/qq_16500963/article/details/132133125, http://cs.williams.edu/~dbarowy/cs334s18/assets/p37-detlefs.pdf, https://tech.meituan.com/2016/09/23/g1.html, https://hllvm-group.iteye.com/group/topic/44381

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaJVMGarbage Collectionperformance tuningg1gc
Ops Development Stories
Written by

Ops Development Stories

Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.