Question 14 · Section 3

What is ZGC?

4. Monitor Allocation Stall in logs 5. CPU overhead 5-15% — plan for it

Language versions: English Russian Ukrainian

Junior Level

ZGC (Z Garbage Collector) — collector with minimal pauses (< 1 ms), independent of Heap size. Throughput is 5-15% lower than G1.

Main advantage: Pauses are practically independent of Heap size and usually < 1 ms. Under extreme load, deviations are possible.

When to use:

  • Real-time systems
  • High-frequency trading
  • When SLA < 10 ms

Middle Level

Key Technologies

1. Colored Pointers:

64-bit pointer:
  Bits 0-41: object address
  Bits 42-45: metadata (GC state)

→ GC understands object status just by reading the pointer
→ Without accessing object memory!

Colored Pointers — in 64-bit pointers, ZGC uses upper bits
to store metadata (generation, finalizable, weak, etc.).
JVM "colors" pointers, saving a separate data structure.

2. Load Barriers:

On every reference read:
  → Check pointer color
  → If object moved → fix address (Self-healing)
  → overhead ~5-15% CPU

Load Barriers — checks on EVERY reference read. If pointer
is "wrong" (object moved), Load Barrier automatically
fixes the pointer (Self-Healing).

3. Concurrent Evacuation:

Objects moved WITHOUT stopping the application!
  → Unlike G1 (Evacuation = STW)
  → Pause only for scanning GC Roots

ZGC vs G1

Criterion G1 ZGC
Pause 20-200 ms < 1 ms
Throughput High -5-10%
Max Heap 64 GB 16 TB
Barriers Write Load

Generational ZGC (Java 21+)

Before Java 21: single generation
  → Scanned entire Heap on every collection

Before Java 21, ZGC was non-generational — this caused Allocation Stalls
at high allocation rates. Generational ZGC (Java 21+) solves
this problem.

Java 21+: Young and Old generations
  → -50% CPU overhead
  → Allocation Stalls almost disappeared

When NOT to use

❌ CPU bound (90%+) → Load Barriers will make it worse
❌ Heap < 4 GB → G1 is more efficient
❌ 32-bit systems → ZGC requires 64-bit

Tuning

-XX:+UseZGC -XX:+ZGenerational  # Java 21+
-XX:SoftMaxHeapSize=24g          # Aggressive memory return
-XX:ConcGCThreads=4              # GC threads

Senior Level

Multi-mapping

One physical memory area mapped to 3 virtual addresses
  → Different metadata bit combinations
  → OS doesn't see pointer conflict
  → Enables "colored" pointers to work

Multi-mapping — technique of mapping one Heap area to several
virtual addresses, to encode metadata in pointer addresses.

Self-Healing Pointers

Load Barrier on read:
  1. Read pointer
  2. Check Remapped bit
  3. If not Remapped → object moved
  4. Compute new address
  5. Update pointer in Heap (CAS)
  6. Return new address

→ Pointer "heals" itself on every read

Allocation Stall Deep Dive

Cause: GC cannot mark garbage fast enough
  → Application threads wait for memory

Solutions:
  1. Increase Heap
  2. Increase ConcGCThreads
     `ConcGCThreads` defaults to number of cores / 4.
     Increase if you see Allocation Stall; decrease if GC takes too much CPU.
  3. Generational ZGC (Java 21+)
  4. Decrease Allocation Rate

Best Practices

  1. Java 21+ — use Generational ZGC
  2. ConcGCThreads = number of cores / 4
  3. SoftMaxHeapSize for containers
  4. Monitor Allocation Stall in logs
  5. CPU overhead 5-15% — plan for it

Senior Summary

  • ZGC = Colored Pointers + Load Barriers + Conc Evacuation
  • Pauses < 1 ms are constant, independent of Heap
  • Generational (Java 21+) = -50% overhead
  • Self-healing pointers via Load Barriers
  • Allocation Stall = main risk
  • CPU overhead 5-15% — price for low latency

Interview Cheat Sheet

Must know:

  • ZGC: pauses < 1 ms, independent of Heap size (up to 16 TB); throughput 5-15% lower than G1
  • Colored Pointers: upper bits of 64-bit pointer store metadata (generation, GC state)
  • Load Barriers: on every reference read, check pointer color + Self-healing (if object moved)
  • Concurrent Evacuation: objects moved WITHOUT STW (unlike G1, where Evacuation = STW)
  • Multi-mapping: one physical Heap area mapped to 3 virtual addresses for metadata encoding
  • Generational ZGC (Java 21+): split into Young/Old → -50% CPU overhead, Allocation Stalls almost disappeared
  • When NOT to use: CPU bound (90%+), Heap < 4 GB, 32-bit systems

Common follow-up questions:

  • Why is ZGC slower than G1 in throughput? — Load Barriers on every reference read add 5-15% CPU overhead
  • What is Allocation Stall in ZGC? — GC cannot mark garbage fast enough → application threads wait; solutions: increase Heap, ConcGCThreads, or Generational ZGC
  • What are Self-Healing pointers? — Load Barrier reads pointer → checks Remapped bit → if object moved, computes new address and updates pointer (CAS)
  • Why Multi-mapping? — One Heap area to 3 virtual addresses → metadata encoding in addresses without pointer conflict

Red flags (DO NOT say):

  • “ZGC uses Write Barriers” — ZGC uses Load Barriers (on read); G1 uses Write Barriers (on write)
  • “ZGC works on 32-bit systems” — ZGC requires 64-bit system (Colored Pointers use upper bits)
  • “ZGC is always better than G1” — for CPU-bound or batch processing, G1 gives better throughput

Related topics:

  • [[12. What GC algorithms exist]]
  • [[13. What is G1 GC]]
  • [[15. What is Shenandoah GC]]
  • [[16. What is stop-the-world]]
  • [[17. Which GCs minimize stop-the-world pauses]]