The full picture
🎬 Generational garbage collection
1 / 5The heap is split by object age: Eden + two survivor spaces (young generation) and the old generation. New objects are allocated in Eden — allocation is just a pointer bump.
Why copying wins for the young gen: a copying collector touches only live objects. If 95% of Eden is dead, a minor GC moves 5% and resets the allocation pointer — allocation itself stays a bump-the-pointer operation (with per-thread TLABs so threads don't contend). The old generation can't use pure copying (too much live data), so collectors there mark live objects and either compact (Parallel, G1 mixed collections) or handle it concurrently in regions (G1, ZGC, Shenandoah).
- GC roots — thread stacks, static fields, JNI handles: tracing starts here; anything unreachable is garbage (reference counting is not used — cycles).
- Card table / remembered sets — track old→young pointers so a minor GC doesn't scan the whole old gen.
- Premature promotion — survivor spaces too small or allocation spikes push short-lived objects into old gen, turning cheap minor GCs into expensive old-gen churn. A classic tuning finding.
- Stop-the-world — even 'concurrent' collectors have brief pauses; young collections in G1/Parallel are fully STW but usually a few ms.