Garbage Collection: Lifecycle, Algorithms & STW
HotSpot reclaims unreachable heap objects automatically. This page is the interactive home for how an object ages (Eden β Survivors β Old β reclaimed), which algorithms young/old use, and how collectors evolved to shrink Stop-The-World (STW) pauses.
For JVM architecture (Heap, Stack, PC, Metaspace) see JVM Internals.
1. Why Generational GC?
Weak generational hypothesis:
- Most objects die young (request DTOs, short-lived builders, temporaries).
- Objects that survive early collections tend to live a long time (singletons, caches, pools).
HotSpot splits the Java Heap into a Young generation (cheap, frequent Mark-Copy) and an Old generation (rarer, more expensive cycles). That split is why S0/S1 exist and why Minor GC is usually cheap compared to Full GC.
2. Heap Layout: Eden, S0, S1, Old
Click regions for ratios, GC role, and flags.
Heap Memory (GC-Managed Shared Area)
Capacity Ratio: 100% of Heap Allocation
Overview: The primary memory workspace of the JVM where all objects, class instances, and array payloads are allocated.
- GC Role & Management: Scanned continuously by minor, major, and mixed GC threads to recover unreachable blocks.
- JVM Sizing Flags:
- -Xms (Initial Heap size)
- -Xmx (Maximum Heap size)
- -XX:MinHeapFreeRatio
- -XX:MaxHeapFreeRatio
π‘ Click on any segment (Heap, Young Gen, Eden, S0, S1, or Old Gen) in the diagram above to inspect JVM memory sizing parameters.
| Space | Role |
|---|---|
| Eden | Birthplace of almost all new allocations (TLAB) |
| S0 / S1 | Twin survivor spaces; one is empty (To) before each young GC; roles flip |
| Old (Tenured) | Long-lived objects after age threshold or survivor overflow |
Locals vs objects: method locals and parameters live on the stack and vanish when the frame returns. Only heap objects go through Eden β Survivor β Old.
3. Object Lifecycle (Animate)
Follow one object from allocation to reclamation. Press βΆ Animate or click a stage.
S0 and S1 swap From/To each Minor GC. Age lives in the object header until promotion or death in Young.
Lifecycle in one breath
- Allocate in Eden.
- Minor GC copies live Eden objects into a Survivor (To); Eden is wiped.
- Next Minor GC: live objects in From + Eden copy into the other Survivor; age++; spaces swap.
- Age β₯
-XX:MaxTenuringThreshold(default 15) or Survivor pressure β promote to Old. - When unreachable from GC Roots, a later Old / mixed / concurrent cycle reclaims the memory.
4. How GC Decides βGarbageβ
HotSpot does not use reference counting (circular refs would leak). It uses reachability analysis from GC Roots:
- Locals / parameters on active thread stacks
- Static fields
- JNI references
- Threads / some internal JVM handles
Anything not reachable from a root is garbage β even if objects still point at each other.
A Java memory leak is usually βstill reachable from a root but forgotten by the appβ (static Map, ThreadLocal, listeners) β GC cannot help until the reference is cleared.
5. Algorithms & STW Evolution
Select a collector on the timeline, then an algorithm chip. Highlighted chips are the ones that collector relies on.
Default on modern HotSpot. Heap is split into equal regions (Eden/Survivor/Old/Humongous). G1 collects regions with the most garbage first under a pause-time goal, using concurrent marking and young/mixed evacuations.
- Remembered sets track cross-region refs so a region can be collected without scanning the world.
- SATB write barrier during concurrent mark.
- Mixed GC: young + selected old regions in one pause window.
- Still has STW β engineered to meet -XX:MaxGCPauseMillis, not zero.
- to-space exhausted / evacuation failure β Full GC (look for Pause Full in logs).
- Humongous allocation storms fragment region map.
- Tune pause goal + heap size together; tiny heap + tiny pause is impossible.
- Default choice unless latency SLO demands ZGC.
-XX:+UseG1GC-XX:MaxGCPauseMillis=200-XX:InitiatingHeapOccupancyPercentSimulate Mark-Copy (young Minor GC) or Mark-Compact (old slide) with moving arrows β one focused sim, not every collector.
Eden is full of live (green) and dead (gray) objects. From may hold survivors from the last cycle. To is empty β required spare space for Mark-Copy.
- Young layout: Eden + From + To (S0/S1 with flipped roles).
- Dead objects are never visited one-by-one later β only live ones are copied.
- STW begins: mutator threads pause for the young collection.
- Cost will scale with live bytes in Eden+From, not with how many dead objects exist.
Mark-Copy: evacuate live objects into empty To, abandon dead space, flip survivors.
Long STW freezes TCP handling β Kubernetes probes can kill a pod that is only βpaused,β not dead. That operational pain is why G1 pause goals and ZGC concurrent relocate exist.
6. G1 Regions
G1 divides the heap into equal-sized regions. Each region is Eden, Survivor, Old, or Humongous. Click for region semantics.
Eden Region (Young Generation)
Overview: Logical young generation region. Sized dynamically based on allocation throughput.
- Tuning flags: -XX:G1NewSizePercent (Initial size, default 5%) | -XX:G1MaxNewSizePercent (Max size, default 60%)
- GC Collection Behavior: Minor GCs evacuate surviving objects to Survivor regions, emptying the Eden regions completely to become Free.
- Under the Hood Mechanics:
- Objects are allocated here via TLABs to avoid synchronization locks.
- Sizing is adjusted dynamically by G1 between collections to meet user pause time targets (-XX:MaxGCPauseMillis).
π‘ Click on any region box (Eden, Survivor, Old, Humongous, Free) on the grid to inspect its logical partition rules.
- Young GC: evacuate Eden + Survivors into survivor/old regions.
- Concurrent mark: find reclaimable Old regions.
- Mixed GC: young + high-garbage Old regions in one pause budget (
MaxGCPauseMillis). - Full GC in logs (
Pause Full) means evacuation/concurrent cycle failed to keep up β investigate promotion, humongous objects, or heap size.
7. Flags Cheatsheet
| Flag | Meaning |
|---|---|
-Xms / -Xmx | Heap size (keep headroom for non-heap RSS in containers) |
-Xmn / -XX:NewRatio | Young size |
-XX:SurvivorRatio | Eden vs each Survivor (default 8 β ~8:1:1) |
-XX:MaxTenuringThreshold | Max age before promotion (default 15) |
-XX:+UseG1GC | G1 (default JDK 9+) |
-XX:MaxGCPauseMillis | G1 pause goal (soft) |
-XX:InitiatingHeapOccupancyPercent | When G1 starts concurrent mark |
-XX:+UseZGC / -XX:+ZGenerational | ZGC (+ generational on JDK 21+) |
-Xlog:gc* | Unified GC logging |
8. Interview Hooks
- Explain S0/S1 From/To flip and why one survivor is empty after a young GC.
- Parallel vs concurrent: Parallel = many GC threads but STW; concurrent = mutators run during mark/relocate.
- Why Mark-Copy for Young and why whole-heap copy is a bad Old strategy.
- Premature promotion symptoms and how Survivor sizing / tenuring threshold interact.
- When to stay on G1 vs move to ZGC for p99 latency.
