Backend Development 25 min read

JVM Performance Optimization Part 3 – Garbage Collection

This article explains Java's memory model and garbage collection mechanisms, covering reference counting, tracing collectors, copying and mark‑sweep algorithms, parallel and concurrent collectors, generational GC, and compression techniques, while discussing their trade‑offs, tuning considerations, and impact on application performance.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
JVM Performance Optimization Part 3 – Garbage Collection

This article is the third part of a JVM performance optimization series, introducing Java's memory model and garbage collection (GC) mechanisms for beginners.

GC is the process of reclaiming memory occupied by unreachable Java objects; reachable objects are retained while unreachable ones are freed for new allocations.

Understanding the Java heap, which is allocated via the -Xmx flag, is essential because a full heap triggers GC, and GC only runs at safe points when all threads are at a safe point.

GC must quickly free unreachable objects to prevent OOM errors and must minimize impact on latency and throughput.

Two main GC approaches : reference counting and tracing collectors. Reference counting tracks the number of references to each object and immediately frees objects with zero references, but it cannot handle cyclic references. Tracing collectors start from root objects, mark reachable objects, and then reclaim unmarked memory.

Tracing collector algorithms include copying and mark‑sweep. Copying collectors move live objects from a “from” space to a “to” space, eliminating fragmentation but requiring stop‑the‑world pauses and sufficient space in the “to” region.

Mark‑sweep collectors, widely used in production JVMs (e.g., CMS, G1, ZGC), mark live objects and then sweep unmarked regions, placing reclaimed memory into free lists; they can suffer from long pause times proportional to heap size and live data.

Parallel collectors run GC phases on multiple threads but are still stop‑the‑world, affecting latency‑sensitive applications. Concurrent collectors overlap GC work with application threads, requiring heuristics to decide safe points for phases and to avoid long re‑mark loops.

Generational GC divides the heap into young and old generations, assuming most objects die young; promotion failures and fragmentation can still occur in the old generation, requiring tuning of generation sizes and promotion rates.

Compression (heap compaction) is the only way to fully eliminate fragmentation by moving live objects together, but it incurs stop‑the‑world pauses that grow with the amount of live data.

The article concludes that while tuning can delay OOM errors, over‑tuning is risky; understanding GC algorithms, their trade‑offs, and appropriate tuning for the workload is essential for optimal Java application performance.

JavaJVMperformance optimizationMemory ManagementGarbage CollectionGC Algorithms
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.