Why you should not call System.gc()?
4. Don't catch OOME via System.gc() 5. Find the leak, don't "help" GC
Junior Level
System.gc() — bad practice because:
- Stops the application — all threads wait
- GC is smarter than you — knows when to clean itself
- Wastes CPU — often without benefit
// ❌ Don't do this!
System.gc(); // "Helping" GC
// ✅ Trust the JVM
// GC will decide when it's needed
Middle Level
Destruction of Adaptive Models
Modern GCs (G1, ZGC) are self-learning:
→ Allocation Rate
→ Promotion Rate
→ Pause Time Goals
System.gc() = external shock:
→ Resets statistics
→ GC relearns from scratch
→ Unpredictable pauses
Concurrent Mode Failure
Concurrent Mode Failure (G1) — concurrent marking didn't finish in time,
Old Gen filled up → fallback to Full GC. This is the longest pause in G1.
System.gc() can provoke this scenario if called at the wrong moment.
How to Find the Culprit
# 1. GC Logs
-Xlog:gc*
→ "Pause Full (System.gc())"
# 2. JFR
→ "System GC" event
→ Full stack trace
# 3. Solution
-XX:+ExplicitGCInvokedConcurrent # Concurrent
# or
-XX:+DisableExplicitGC # Ignore
Senior Level
JIT Deoptimization
Full GC → class unloading → deoptimization of hot methods.
Code Cache is cleaned separately (CodeCache sweeper).
→ After GC: code interpretation
→ Throughput drops for seconds
→ "Sledgehammer for Swiss watches" — System.gc() brutally stops
all JVM optimizations for forced garbage collection.
GC Thrashing
Attempting to "cure" OOM via System.gc():
→ Frees tiny amounts of memory
→ Spends 95% CPU on GC
→ Masks the real problem
→ Better to crash and restart
Production: DisableExplicitGC
-XX:+DisableExplicitGC
# → Ignores all System.gc() calls
# → Except Direct Buffers (be careful!)
# Alternative:
-XX:+ExplicitGCInvokedConcurrent
# → Concurrent GC instead of Full GC STW
Best Practices
- Only legitimate use case — benchmarks (JMH)
- JFR to find the caller
- ExplicitGCInvokedConcurrent for production
- Don’t catch OOME via System.gc()
- Find the leak, don’t “help” GC
Senior Summary
- System.gc() = “sledgehammer for Swiss watches” — brutally stops all JVM optimizations
- Destroys adaptive GC models
- Concurrent Mode Failure → Full GC STW
- JIT deoptimization → Throughput loss
- JFR = find the caller
- DisableExplicitGC or ExplicitGCInvokedConcurrent
Interview Cheat Sheet
Must know:
- System.gc() — anti-pattern: Full GC = STW (seconds), resets GC adaptive statistics, JIT deoptimization of hot methods
- G1/ZGC are self-learning (Allocation Rate, Promotion Rate, Pause Time Goals); System.gc() = external shock → GC relearns from scratch
- Concurrent Mode Failure (G1): concurrent marking didn’t finish → Old Gen full → Full GC STW; System.gc() can provoke this
- JIT deoptimization: Full GC → class unloading → hot methods → interpretation → throughput drops for seconds
- GC Thrashing: attempting to “cure” OOM via System.gc() → 95% CPU on GC → masks real problem
- Production:
-XX:+ExplicitGCInvokedConcurrent(concurrent GC instead of STW) or-XX:+DisableExplicitGC(ignore, careful with Direct Buffers!) - Only legitimate use case — benchmarks (JMH)
Common follow-up questions:
- Why does System.gc() destroy adaptive models? — G1/ZGC accumulate statistics (allocation rate, promotion rate); System.gc() = sudden Full GC → statistics reset → GC “forgets” application behavior
- What is Concurrent Mode Failure? — G1 concurrent marking didn’t finish before Old Gen filled → fallback to Full GC (longest pause in G1)
- How to find who calls System.gc()? —
-Xlog:gc*(look for “Pause Full (System.gc())”); JFR (“System GC” event with full stack trace) - Why does JIT deoptimization happen? — Full GC → class unloading → JIT-compiled methods removed → recompiled from scratch
Red flags (DO NOT say):
- “I call System.gc() for preventive maintenance” — GC knows itself; manual call = STW + destruction of adaptive models
- “I catch OOME and call System.gc()” — GC Thrashing: 95% CPU on GC; better fail-fast and restart
- “System.gc() improves performance” — “sledgehammer for Swiss watches”; brutally stops all JVM optimizations
Related topics:
- [[27. Can you manually invoke GC]]
- [[4. What is Garbage Collection]]
- [[13. What is G1 GC]]
- [[19. What happens on OutOfMemoryError]]
- [[16. What is stop-the-world]]