Java Garbage Collection (GC) Cheatsheet
Garbage Collection (GC) in Java is an automatic memory management process that helps reclaim memory used by objects that are no longer referenced. The JVM takes care of memory allocation and deallocation, reducing the need for manual memory management, but understanding GC behavior is important for optimizing performance.
1. GC Basics
- Automatic Memory Management: The JVM automatically manages the heap memory by removing objects that are no longer referenced or used, freeing up space for new objects.
- Heap: The area of memory where all objects are stored. It is divided into different regions for better GC performance.
2. Key Garbage Collection Concepts
- Reachability: An object is considered “reachable” if it can be accessed from a thread or from static fields, otherwise it is “garbage” and can be collected.
- Garbage: Any object that is no longer reachable by any live thread or static reference is eligible for garbage collection.
- GC Roots: Starting points used to trace reachable objects. These include:
- Active threads
- Static variables
- Local variables in methods
3. GC Phases
Minor GC (Young Generation GC)
- Young Generation is where newly created objects are allocated.
- Consists of three areas: Eden, Survivor Space (S0, S1).
- Process:
- Eden Space: Newly created objects are initially placed here.
- If the Eden space fills up, a Minor GC is triggered.
- Objects that survive the Minor GC are moved to one of the Survivor Spaces.
- Objects that survive several Minor GCs are eventually promoted to the Old Generation.
Major GC (Full GC or Old Generation GC)
- Old Generation: Stores long-lived objects that have survived many minor GCs.
- Full GC: Occurs when the Old Generation is full. It is much more time-consuming than a minor GC because it also collects unreachable objects from both the Old and Young Generation.
4. Garbage Collection Algorithms
- Serial GC:
- Single-threaded garbage collection.
- Best suited for single-processor systems.
-XX:+UseSerialGC
- Parallel GC (also known as Throughput Collector):
- Uses multiple threads to collect garbage in the Young Generation (minor GC).
- Useful for multi-core processors.
-XX:+UseParallelGC
- Concurrent Mark-Sweep (CMS):
- Aims to minimize GC pauses by doing most of the work concurrently with application threads.
- Phases:
- Initial Mark: Marks reachable objects in the Old Generation.
- Concurrent Mark: Marks objects in parallel.
- Concurrent Preclean: Cleans up some references before final remark.
- Final Remark: Marks the remaining unreachable objects.
- Concurrent Sweep: Reclaims memory concurrently.
-XX:+UseConcMarkSweepGC
- Suitable for low-latency applications but can cause fragmentation.
- G1 Garbage Collector (Garbage-First):
- Designed for large heap sizes with low-latency requirements.
- Divides the heap into regions and performs garbage collection in a manner that prioritizes the most critical regions.
- Phases:
- Young GC: Collects Young Generation.
- Mixed GC: Collects both Young and Old Generation.
- Concurrent Phase: Performs some actions concurrently with application threads.
- Final Cleanup: Cleans up after a cycle.
-XX:+UseG1GC
- Balances throughput and low pause times.
- ZGC (Z Garbage Collector):
- A low-latency garbage collector.
- Aims for pause times under 10ms, even with very large heap sizes.
- Phases: Includes concurrent marking and remapping, parallel evacuation.
-XX:+UseZGC
- Shenandoah GC:
- Another low-latency garbage collector, similar to ZGC.
- Aims for very short pause times even for large heaps.
-XX:+UseShenandoahGC
5. JVM Options for GC Tuning
- Heap Size Options:
-Xms
– Initial heap size.-Xmx
– Maximum heap size.-XX:MaxMetaspaceSize
– Maximum metaspace size (JVM 8+).- GC Logging:
-XX:+PrintGCDetails
– Logs detailed GC information.-XX:+PrintGCDateStamps
– Includes timestamps in GC logs.-Xlog:gc*
– Unified logging for GC activities (JVM 9+).-XX:+PrintGCApplicationStoppedTime
– Logs time spent in GC pauses.- GC Tuning:
-XX:+UseG1GC
– Use the G1 Garbage Collector.-XX:MaxGCPauseMillis=<time>
– Target maximum pause time (in milliseconds) for G1.-XX:G1HeapRegionSize=<size>
– Set G1 region size (default is 2MB).-XX:ParallelGCThreads=<n>
– Set the number of threads for Parallel GC.-XX:ConcGCThreads=<n>
– Set the number of threads for concurrent phases in CMS/G1.- Other GC Flags:
-XX:+DisableExplicitGC
– Prevent explicit garbage collection calls (System.gc()
).-XX:SurvivorRatio=<ratio>
– Set the ratio of Eden to Survivor space.-XX:TargetSurvivorRatio=<ratio>
– Set the desired survivor space ratio (for G1).
6. JVM GC Behavior and Analysis
- GC Pause Time: Refers to the duration during which the application is paused while GC is running. Minimizing GC pauses is crucial for real-time applications.
- GC Throughput: The ratio of time spent executing the application vs. time spent performing GC. Higher throughput means more application work and less GC overhead.
- Heap Dump: A snapshot of the heap memory, useful for debugging memory leaks and analyzing object allocation patterns.
- Command:
-XX:+HeapDumpOnOutOfMemoryError
(creates a heap dump when anOutOfMemoryError
is thrown). - Tool:
jmap
for generating heap dumps,jhat
for analyzing them. - GC Root Analysis: Tools like
jcmd
or profilers can help identify GC roots and trace references preventing objects from being collected.
7. Monitoring and Profiling Tools
- JVisualVM: A GUI tool for monitoring the JVM, including GC activity.
- JConsole: Provides real-time monitoring for memory usage, GC, and application performance.
- GC Logs: Analyze GC logs to track memory usage, GC times, and identify inefficiencies in garbage collection.
- JFR (Java Flight Recorder): Collects low-level events, including GC events, for detailed performance analysis.
- Prometheus / Grafana: Can be integrated with JVM to monitor GC metrics in real-time for larger production systems.
8. Types of GC Pauses
- Young GC Pause: Short pause, typically caused by minor GC. It affects only the Young Generation.
- Old GC Pause: Longer pause, occurs when GC is cleaning the Old Generation (Full GC).
- Stop-the-World (STW): During GC, all application threads are paused. This occurs during certain phases like the Mark and Sweep phases.
9. GC Performance Optimization Tips
- Tune Heap Sizes:
- Ensure that
-Xms
and-Xmx
values are appropriately set based on your application’s memory needs. - If you frequently run into Full GCs, increase the heap size.
- Adjust GC Algorithm:
- Use G1 GC if you need to balance low-latency with throughput, or CMS for low-latency applications.
- Parallel GC is great for high-throughput systems that can tolerate some pauses.
- Tune Survivor Space Size:
- Adjust
-XX:SurvivorRatio
and-XX:TargetSurvivorRatio
to optimize how objects are promoted from the Young Generation.
- Avoid Frequent Full GCs:
- Full GCs are expensive and can significantly affect performance. Tune the heap size and choose an appropriate GC strategy to minimize them.
- Use G1 GC for Large Heaps:
- If you are dealing with large heap sizes (several GBs), G1 GC can be more efficient and predictable than CMS or Parallel GC.
10. Common Garbage Collection Issues
- Frequent Full GCs: Often caused by a small Old Generation or inadequate heap size.
- Memory Leaks: When objects are unintentionally retained, preventing GC from collecting them. Use heap dumps or profiling tools to identify and fix them.
- Long Pause Times: Can be caused by large objects or full GC cycles. G1, ZGC, or Shenandoah may help minimize pauses.
11. Example GC JVM Options
- **Enable G1 GC with low pause time goals**:
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1HeapRegionSize=8M
- Use Parallel GC for throughput:
-XX:+UseParallelGC -XX:ParallelGCThreads=4
- Enable GC logging for troubleshooting:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xlog:gc*
Understanding Java Garbage Collection and being able to tune it effectively is crucial for maintaining optimal application performance. This cheat sheet provides the basics, along with JVM options and strategies for dealing with memory management.