How the JVM Determines Object Liveness and Its Garbage Collection Algorithms
This article explains the JVM memory model, how the JVM decides whether an object is alive using reference counting and reachability analysis, and describes the main garbage‑collection algorithms—including mark‑sweep, mark‑compact, copying, and generational collection—along with their advantages and drawbacks.
In the JVM memory model the heap is divided into the young generation and the old generation; the young generation holds short‑lived objects while the old generation stores long‑lived ones, and each region uses different garbage‑collection strategies.
The JVM determines whether an object is garbage by applying two main techniques: reference counting and reachability analysis (GC Roots).
Reference Counting works by maintaining a count for each object; when the count drops to zero the object is considered unreachable and can be reclaimed. This method cannot handle cyclic references.
Reachability Analysis (GC Roots) treats an object as alive if it can be reached from a set of root references, which include:
Objects referenced from the JVM stack (local variables in stack frames).
Static fields in the method area.
Objects referenced by constants in the method area.
Objects referenced by native code via the JNI stack.
When a method finishes, its stack frame and local variables are popped, removing the corresponding GC Roots and allowing the previously reachable objects to be collected.
Below is a simple Java example used to illustrate object lifetimes:
public class App {
public static void main(){
checkFile("/");
}
public static boolean checkFile(String path ){
File file = new File(path);
return file.exists();
}
}During the execution of checkFile , the local variable file is a GC Root. After the method returns, the stack frame is removed, the file reference disappears, and the File object becomes eligible for garbage collection.
The JVM provides several garbage‑collection algorithms:
Mark‑Sweep : Marks reachable objects from the GC Roots, then sweeps away unmarked ones. It is fast but can leave memory fragmentation.
Mark‑Compact (Mark‑Sweep with Compaction) : After marking, it moves live objects to eliminate gaps, producing contiguous free space at the cost of higher overhead.
Copying : Splits the heap into two equal regions; live objects are copied to the other region during collection, and the whole original region is cleared. This yields fast allocation but uses only about 50% of the heap.
Generational Collection : Applies different algorithms to the young and old generations. The young generation (Eden + two Survivor spaces) typically uses the copying algorithm, while the old generation uses mark‑sweep or mark‑compact.
In a typical 1 GB heap, the young generation might be divided as 800 MB Eden, 100 MB Survivor 1, and 100 MB Survivor 2 (8:1:1 ratio). Objects are allocated in Eden; when a Minor GC occurs, surviving objects are moved to a Survivor space, freeing Eden for new allocations and keeping overall heap utilization around 90% without fragmentation.
Overall, the JVM’s combination of reference counting, reachability analysis, and multiple garbage‑collection strategies enables efficient memory management for Java applications.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
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.