Mastering Java Garbage Collection: Algorithms, Regions, and Tuning Tips
This article provides a comprehensive overview of Java's automatic garbage collection, covering memory regions, identification methods, core algorithms such as mark‑sweep, copying, and generational collection, detailed explanations of various collectors (Serial, CMS, G1, etc.), and practical tuning insights for optimal performance.
Preface
Java's most notable feature compared to C/C++ is automatic garbage collection (GC), which frees developers from manual memory management and boosts productivity, though its operation is often invisible to programmers.
Understanding GC is essential for performance tuning and troubleshooting; for example, Meituan improved service response times by adjusting JVM GC parameters.
JVM Memory Regions
GC primarily works on the heap; other regions do not require GC.
Virtual Machine Stack : thread‑private, holds stack frames, local variables, operand stack, etc.; not subject to GC.
Native Method Stack : similar to VM stack for native methods; not subject to GC.
Program Counter : per‑thread line number indicator; not subject to GC.
Native Memory (Off‑heap) : includes Metaspace and Direct Memory; not managed by GC.
Heap : the only region where GC occurs, containing object instances and arrays.
How to Identify Garbage
GC determines which heap objects are unreachable.
Reference Counting
Each object maintains a count of references; when the count reaches zero, the object is collectible. String ref = new String("Java"); If the reference is set to null, the object becomes eligible for collection.
Reference counting cannot handle cyclic references.
public class TestRC {
TestRC instance;
public TestRC(String name) {}
public static void main(String[] args) {
TestRC a = new TestRC("a");
TestRC b = new TestRC("b");
a.instance = b;
b.instance = a;
a = null;
b = null;
}
}Even after setting a and b to null, the two objects reference each other and remain uncollected.
Reachability Algorithm
Modern JVMs use GC Roots as starting points and traverse object graphs; objects not reachable from any GC Root are considered garbage.
GC Roots include:
Objects referenced from the VM stack (local variables).
Static fields in the method area.
Constants in the method area.
JNI references in the native method stack.
VM Stack Roots Example
public class Test {
public static void main(String[] args) {
Test a = new Test();
a = null;
}
}Static Field Roots Example
public class Test {
public static Test s;
public static void main(String[] args) {
Test a = new Test();
a.s = new Test();
a = null;
}
}Constant Roots Example
public class Test {
public static final Test s = new Test();
public static void main(String[] args) {
Test a = new Test();
a = null;
}
}JNI Roots Example
JNIEXPORT void JNICALL Java_com_pecuyu_jnirefdemo_MainActivity_newStringNative(JNIEnv *env, jobject instance, jstring jmsg) {
// cache String class
jclass jc = (*env)->FindClass(env, "java/lang/String");
}Garbage Collection Main Methods
Mark‑Sweep
Copying
Mark‑Compact
Generational Collection
Mark‑Sweep
Marks reachable objects, then sweeps away unmarked ones, leading to memory fragmentation.
Copying
Divides the heap into two regions (From and To); live objects are copied to the To space, eliminating fragmentation but halving usable heap size.
Mark‑Compact
Marks reachable objects, then compacts them to one end of the heap, removing fragmentation at the cost of moving objects.
Generational Collection
Combines the above algorithms, separating objects by age into Young (Eden, S0, S1) and Old generations. Most objects die young, so Minor GC (young) uses copying, while Old generation GC typically uses mark‑compact.
Collector Types
Different collectors target different generations.
Young‑generation collectors: Serial, ParNew, Parallel Scavenge.
Old‑generation collectors: CMS, Serial Old, Parallel Old.
Unified collectors: G1.
Serial Collector
Single‑threaded, suitable for client‑mode JVMs where pause times are acceptable.
ParNew Collector
Multithreaded version of Serial, often paired with CMS for server‑mode JVMs.
Parallel Scavenge Collector
Multithreaded, focuses on maximizing throughput rather than minimizing pause times.
CMS Collector
Concurrent collector aiming for minimal STW pauses; uses mark‑sweep for the old generation.
G1 (Garbage‑First) Collector
Region‑based collector that provides predictable pause times, reduces fragmentation, and can be tuned for desired latency.
Summary
The article outlines Java GC principles, identification methods, core algorithms, and the characteristics of major collectors, emphasizing the importance of choosing the right collector combination based on application scenarios to achieve optimal performance.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
