Question 13 · Section 3

What is G1 GC?

G1 replaced Parallel GC as the default because it provides predictable pauses. The name "Garbage First" means: collect regions with the most garbage first (maximum efficiency pe...

Language versions: English Russian Ukrainian

Junior Level

G1 (Garbage First) — the default garbage collector in Java (since Java 9).

G1 replaced Parallel GC as the default because it provides predictable pauses. The name “Garbage First” means: collect regions with the most garbage first (maximum efficiency per cycle).

Main idea: Divides Heap into regions and collects the “dirtiest” ones first.

Simple analogy: Cleaning a house — you clean the dirtiest rooms first, not the entire house at once.

Advantages:

  • Predictable pauses (configurable)
  • Works well on Heap from 4 GB to tens of GB. Above 32 GB, Compressed OOPs are disabled — this affects all GCs, not just G1.
  • Balance between speed and pauses

Middle Level

G1 Regions

Heap split into 2048 regions (1-32 MB each)

Region types:
  Eden — new objects
  Survivor — survivors
  Old — long-lived
  Humongous — large objects (> 50% of region)
  Free — free

Remembered Sets (RSet)

Each region stores: which OTHER regions reference it

Why:
  → During Young GC, no need to scan entire Old Gen
  → Only regions with references to Young are scanned

Remembered Sets (RSet) — data structure for each region that
tracks incoming references from OTHER regions.
Allows G1 to avoid scanning entire Heap.

Work Cycle

1. Young GC (STW) — copying young objects
2. Concurrent Marking — background Old Gen marking
3. Mixed GC — Young + dirtiest Old regions

Goal: fit within MaxGCPauseMillis

Tuning

-XX:MaxGCPauseMillis=200     # Target pause
-XX:InitiatingHeapOccupancyPercent=45  # Old GC threshold

Senior Level

Collection Set (CSet)

Set of regions to clean in the current cycle

Collection Set (CSet) — set of regions selected for collection
in the current cycle. G1 selects regions with the most garbage.

Young GC:
  → CSet = all Young regions

Mixed GC:
  → CSet = Young + dirtiest Old regions
  → G1 selects to fit within MaxGCPauseMillis

Evacuation Failure

Not enough space in target regions when copying live objects
  → To-space exhausted
  → Full GC (STW!)

Evacuation Failure (To-space exhausted) — when G1 runs out of
space to copy live objects. Fallback to Full GC — long pause.

Causes:
  - Fragmentation
  - Too many live objects

Solution: increase Heap or decrease MaxGCPauseMillis

String Deduplication

-XX:+UseStringDeduplication

G1 finds identical char[] in different Strings
  → Collapses into one reference
  → 5-10% Heap savings

Works only for Strings created via new String() or concatenation.
Strings from literal pool are already deduplicated. Greatest effect for
applications with many duplicate strings.

Generational ZGC vs G1

G1: pauses 20-200 ms, good throughput
ZGC: pauses < 1 ms, -5-10% throughput

Choice: SLA < 10 ms → ZGC, otherwise G1

Generational ZGC requires Java 21+. On Java 17, use G1.

Best Practices

  1. Don’t fix -Xmn for G1 (loses adaptivity)
  2. Don’t set MaxGCPauseMillis too low (< 50 ms)
  3. Tune IHOP for your Promotion Rate
  4. Humongous → increase G1HeapRegionSize
  5. Enable String Deduplication for memory savings
  6. Monitor To-space exhausted

Senior Summary

  • G1 = regional, adaptive GC
  • RSet = Young GC optimization
  • CSet = selects dirtiest regions
  • SATB = concurrent marking algorithm
  • Evacuation Failure = worst case scenario
  • Don’t fix Young Gen — G1 is adaptive
  • MaxGCPauseMillis = main tuning lever

Interview Cheat Sheet

Must know:

  • G1 divides Heap into 2048 regions (1-32 MB); types: Eden, Survivor, Old, Humongous, Free
  • RSet (Remembered Set): each region stores which other regions reference it → Young GC doesn’t scan entire Heap
  • CSet (Collection Set): regions selected for collection in current cycle; G1 selects the “dirtiest”
  • G1 cycle: Young GC (STW) → Concurrent Marking → Mixed GC (Young + dirty Old regions)
  • Evacuation Failure (To-space exhausted): no space to copy live objects → Full GC (STW!)
  • SATB (Snapshot-At-The-Beginning): concurrent marking; Floating Garbage — objects that became garbage after snapshot
  • String Deduplication (-XX:+UseStringDeduplication): G1 collapses identical char[] in String → 5-10% Heap savings

Common follow-up questions:

  • Why shouldn’t MaxGCPauseMillis be set too low (< 50 ms)? — G1 cannot fit → Evacuation Failure → Full GC
  • What is IHOP (InitiatingHeapOccupancyPercent)? — Old Gen threshold (default 45%) at which G1 starts Concurrent Marking; tune for your Promotion Rate
  • What to do about Humongous Objects? — Increase -XX:G1HeapRegionSize (e.g., 16m or 32m) so objects aren’t considered Humongous
  • Why shouldn’t -Xmn be fixed for G1? — G1 adaptively changes Young Gen to achieve MaxGCPauseMillis; fixing breaks adaptivity

Red flags (DO NOT say):

  • “G1 scans entire Old Gen during Young GC” — RSet optimization: only regions with references to Young are scanned
  • “I’ll set MaxGCPauseMillis=10 ms for maximum speed” — G1 cannot fit → To-space exhausted → Full GC
  • “String Deduplication saves memory on String Pool strings” — works only for new String() and concatenation; pool strings are already deduplicated

Related topics:

  • [[8. What are generations in GC]]
  • [[12. What GC algorithms exist]]
  • [[14. What is ZGC]]
  • [[16. What is stop-the-world]]
  • [[10. What is Old Generation (Tenured)]]