7.1 Garbage Collection Fundamentals & Generational Hypothesis
← Back to Chapter 7: Garbage Collection & Serialization
Garbage Collection is the process of automatically finding unused objects in Heap memory and removing them to free memory.
What is Garbage Collection?
In Java, we create objects using new.
User user = new User();
This object is stored in Heap memory.
When we no longer need the object, ideally its memory should be released.
In languages like C/C++, developers often manually release memory. Java does this automatically using Garbage Collection (GC).
What exactly is "Garbage"?
An object that is no longer reachable from the application is called Garbage.
Example:
User user = new User();
user = null;
Initially:
user ───────> User Object
After user = null:
user ──X──> User Object
User Object
↓
Garbage
The object is now eligible for GC.
Important:
Eligible for GC does NOT mean immediately deleted.
The JVM decides when GC should actually run.
Why do we need Garbage Collection?
Without GC Heap memory keeps filling with unused objects. After GC the unused object are removed and memory is released.
Stack vs Heap
Stack contains :
local variables method calls references to objects
Heap contains :
actual objects
Stack:
user reference disappears
Heap:
User object may become unreachable
↓
Eligible for GC
How does Java know an object is unused?
Java mainly uses reachability.
If the objects are not reachable by the GC root objects, they are considered as Garbage.
What are GC Roots?
GC Roots are objects/references from which Java starts checking whether other objects are reachable.
Common GC Roots include:
1. Local variables in active threads
2. Static variables
3. Active Java threads
4. JNI references
5. Some JVM internal references
Does System.gc() perform Garbage Collection?
It is a request/suggestion to the JVM to perform GC.
It does not guarantee that GC will happen immediately.
System.gc();
Runtime.getRuntime().gc();
Another way of requesting GC
Can we force Garbage Collection?
No. You can request it using System.gc().
JVM decides whether and when to perform GC.
How does Garbage Collection actually work?
Application creates objects
↓
Heap fills
↓
GC triggered
↓
Find reachable objects
↓
Identify unreachable objects
↓
Remove/reclaim them
↓
Memory reused
Generational Garbage Collection
- Most objects die shortly after instantiation (e.g. local loop variables, temporary DTOs, HTTP request contexts).
- References from older objects to younger objects are extraordinarily rare.
Heap Division
┌───────────────────────────────────────────┬───────────────────────────────────────────┐
│ Young Generation │ Old Generation │
│ │ (Tenured) │
│ ┌──────────────────────┬─────────┬──────┐ │ ┌───────────────────────────────────────┐ │
│ │ Eden Space │ S0 │ S1 │ │ │ Long-lived survived objects │ │
│ │ (Fresh allocations) │ Survivor│ │ │ │ (Promoted after threshold, e.g. 15) │ │
│ └──────────────────────┴─────────┴──────┘ │ └───────────────────────────────────────┘ │
└───────────────────────────────────────────┴───────────────────────────────────────────┘
Young Generation
Young Generation contains newly created objects.
Old Generation
Old Generation contains objects that have survived for a relatively long time.
GC Phases (Steps of GC)
- Mark: JVM finds objects that are still reachable. It marks the objects that are alive.
- Sweep: JVM removes unreachable objects and frees there memory.
- Compact: After removing garbage, there may be empty gaps. Compaction moves objects together. This makes future allocation easier.
Stop-The-World (STW)
During some GC phases, application threads may need to stop. This is known as Stop-The-World.
Why is Stop-The-World a problem?
But GC pauses application threads causes:
API latency ↑
timeouts
slow application