Garbage Collection
References: Understanding the JVM (3rd Edition, Chinese) , G1 & ZGC deep dive (Chinese)
Is an Object Dead?
Reference Counting
Drawback: they reference each other, so neither count goes to 0; they won’t be collected.
Reachability Analysis
Start from GC Roots and traverse references downward, marking all reachable objects. The traversal paths are “reference chains.”
GC Roots include:
- Objects referenced from local variable tables in JVM stack frames (method params, temps, and the this of instance methods)
- Class static variables (in the method area)
- Constants referenced from the method area
- Native references from the native method stack
- All objects held by synchronized
- JVM-internal refs: Class objects for primitives, permanent exception objects, system class loader
Even if first marked “unreachable,” an object isn’t necessarily collected immediately.
Reference Types
Usually only strong and soft references are used, because soft references help GC performance.
- Strong: Object obj = new Object(); GC never collects it.
- Soft: useful but not essential. Not collected while memory is sufficient; collected when memory is tight.
- Weak: survives only until the next GC, regardless of memory pressure. Created via java.lang.ref.WeakReference
. - Phantom: effectively no reachability; used only to track object lifecycle. When collected, a phantom reference is enqueued so you can know it’s about to be reclaimed.
Collecting Classes and Constants (in Method Area)
Collecting a class requires:
- All instances of the class are collected.
- Its class loader has been collected.
- The corresponding java.lang.Class object is not referenced anywhere and cannot be reached by reflection.
Constants can also be collected when they are no longer referenced.
Generational Collection Theory
Hypotheses:
- Most objects die young.
- The more GCs an object survives, the less likely it dies soon.
Partial collections:
- Young-only (Minor/Young GC)
- Old-only (Major/Old GC)
- Mixed GC: entire young plus part of old
Full-heap collection: entire heap and method area.
Mark–Sweep
Mark live objects first, then sweep unmarked ones.
Cons: slow; leaves memory fragments.
Mark–Copy
Use only half the memory at a time. After marking, copy survivors to the other half, then reclaim the entire original half.
Modern JVMs use copy algorithms for the young gen. With objects dying young, young is split into Eden, S1, S2 (8:1:1). Use Eden+one survivor until GC; then copy survivors into the other survivor.
Con: reduces usable space to half (per region pair).
Mark–Compact
Best for old gen. After sweeping, move survivors to produce contiguous free memory and avoid fragmentation.
Classic Collectors

Serial
Single-threaded and Stop-The-World. Young: copy; Old: compact.
ParNew
Multi-threaded version of Serial for young gen.
Parallel Scavenge
Throughput-oriented. JDK 8 default is Parallel Scavenge + Parallel Old.
Throughput = run time of user code / (user code time + GC time)
-XX:MaxGCPauseMillis controls max GC pause time.
Reducing pause time often means shrinking young gen, which increases GC frequency and may lower throughput.
-XX:GCTimeRatio sets throughput target.
An integer (0–100), the fraction of time allowed for GC.
Serial Old
Old-gen counterpart of Serial.
Parallel Old
Old-gen counterpart of Parallel Scavenge.
CMS
Aims for the shortest pauses. Mark–Sweep; HotSpot’s first concurrent collector.
- Initial Mark: pause to mark roots’ direct references.
- Concurrent Mark: mark reachable objects concurrently with mutators.
- Remark: pause longer to fix up changes during concurrent marking.
- Concurrent Sweep: no pause, but leaves fragmentation.
G1 (Garbage-First)
Server-oriented; high throughput and low pauses. Default since JDK 9. Globally mark–compact; locally mark–copy. No fragmentation.
G1 provides a predictable pause model: e.g., -XX:MaxGCPauseMillis=50 means GC should usually fit within that pause budget.
Uses Mixed GC: divides the heap into equal-sized regions; any region can be treated as young or old.
G1 tracks each region’s “value” (memory reclaimed vs. time cost) and maintains a priority list to meet the pause goal.
- Initial Mark: short pause to mark roots.
- Concurrent Mark: mark reachability with the app running.
- Final Mark: short pause to catch up with changes since concurrent mark.
- Evacuation/Selection: pause and parallel-copy from chosen regions; select by value within pause target; survivors may be copied into consolidated regions; source regions are freed.
ZGC
Low-latency collector targeting sub-10ms pauses at any heap size with minimal throughput impact.
Splits the heap into many differently sized pages.
Interview Prompts
- G1 phases (initial mark with minor GC, concurrent mark, remark, selection/evacuation)
- How G1 achieves MaxGCPauseMillis
- How STW is implemented
- What areas are collected in Full GC
- Why Metaspace replaced PermGen in Java 8; why just enlarging PermGen isn’t sufficient
- How to diagnose OOM and CPU 100%