Detailed explanation
CMS, G1, and ZGC mainly differ in how they trade application throughput, pause latency, memory overhead, and implementation complexity. Concurrent work runs alongside application threads; stop-the-world work suspends them. All three use concurrency, but they differ significantly in which operations still require pauses. For interviews, compare their collection mechanisms and operational trade-offs rather than simply calling one collector faster. JVM version also matters because collector availability and defaults have changed.
CMS, or Concurrent Mark Sweep, was designed to reduce old-generation collection pauses. It performs most marking and sweeping concurrently, but initial marking and remarking require stop-the-world pauses. It normally reclaims old-generation memory without moving surviving objects, so free space can become fragmented. Allocation can fail despite sufficient total free memory if no suitable contiguous block exists. If collection cannot keep up, a concurrent mode failure can trigger an expensive stop-the-world fallback. CMS was deprecated in JDK 9 and removed in JDK 14, so it is relevant mainly to legacy systems.
G1, or Garbage-First, divides the heap into regions that can serve as young or old space. It marks concurrently and uses stop-the-world evacuation pauses to copy live objects out of selected regions, reclaiming and compacting those regions. Mixed collections process young regions together with selected old regions. G1 prioritises collection sets using reclaimable space and estimated collection cost, working towards a configurable pause-time goal through -XX:MaxGCPauseMillis. This is a target, not a guarantee. G1 became the default in JDK 9 for typical server configurations and offers a practical balance of throughput and latency.
ZGC moves much more work, including object relocation, into concurrent phases. Coloured pointers and barriers let application threads access objects correctly while the collector relocates them. It targets sub-millisecond pauses, including on very large heaps, but does not provide hard real-time guarantees. Low pauses come with CPU and memory-headroom requirements; insufficient resources can still cause allocation stalls. Modern ZGC is generational. Choose G1 for a general-purpose starting point and evaluate ZGC when strict latency requirements justify workload-specific benchmarking.
Key points to remember
- CMS concurrently marks and sweeps old space but normally does not compact it; fragmentation is a major limitation.
- CMS was deprecated in JDK 9 and removed in JDK 14.
- G1 uses regions, concurrent marking, and stop-the-world evacuation; its pause-time goal is not a hard deadline.
- ZGC performs marking and relocation largely concurrently, targeting sub-millisecond pauses rather than maximum throughput.
- Select available collectors with -XX:+UseG1GC or -XX:+UseZGC, then compare latency, throughput, CPU usage, and memory needs.
Common mistakes candidates make
- Saying concurrent collectors eliminate all stop-the-world pauses or guarantee application response times.
- Describing G1 evacuation as concurrent, or claiming CMS routinely compacts old-generation memory.
- Choosing ZGC solely because the heap is large, without checking the JDK version, CPU budget, memory headroom, and measured workload behaviour.
Likely follow-up questions
Does setting -XX:MaxGCPauseMillis guarantee that G1 pauses stay below that value?
No; it is a soft goal that influences G1's collection-set and young-generation sizing decisions. A tighter goal can increase collection frequency and reduce throughput, and some pauses can still exceed it.
What is generational ZGC, and which versions support it?
Generational ZGC separates young and old objects to exploit the fact that many objects die young, reducing unnecessary collection work. It was introduced in JDK 21, became ZGC's default mode in JDK 23, and became its only mode in JDK 24.
How would you compare G1 and ZGC for a production service?
Run representative workloads on the intended JDK with realistic CPU limits, heap sizing, and container memory limits. Compare tail response latency, throughput, GC pauses, allocation stalls, CPU consumption, and total process memory rather than judging only average pause time.
Interview tip: Structure your answer around mechanism, pause behaviour, and trade-offs, then mention CMS removal and explain when you would benchmark G1 against ZGC.
