Core Java Part 6 : Garbage Collection & JVM Memory Management
- ๐ 1. Java Object Lifecycle: From Birth to Garbage Collection
- ๐ง 2. Lifecycle Recap
- ๐ง 3. JVM Memory Management: What we as Java Developerโs Must Know
- ๐ 4. Escape Analysis โ Optimize Object Allocation
- ๐งผ 5. Garbage Collection โ How JVM Cleans the Heap
- ๐ง 6. Summary: Java Memory & Object Lifecycle
- โ 7. Tips for Java Memory Efficiency
๐ 1. Java Object Lifecycle: From Birth to Garbage Collection
Everything in Java is an object (well, almost everything). But have we ever wondered what happens to an object behind the scenes, from creation to destruction?
This process is called the Object Lifecycleโand itโs one of the most fundamental things needed to be known as a Java Developer.
๐ ๏ธ Stage 1: Object Creation (Birth)
๐ง Intuition
Think of creating a new car in a factory. We allocate resources (steel, engine, etc.), assemble them, and then bring it to life.
In Java, when we create an object like this:
Car c = new Car();
Hereโs what happens step-by-step:
๐ Under the Hood:
- Memory is allocated on the heap for a new
Car
object. - The object is initialized with default values (e.g.,
0
,null
,false
). - The constructor is called to initialize the object explicitly.
- A reference (
c
) is created to point to that object.
๐ Code Example:
class Car {
Car() {
System.out.println("Car constructor: Object created!");
}
}
Car c = new Car(); // Car constructor: Object created!
๐งช Stage 2: Object Usage (Life)
Once the object is created, it lives in memory, ready to perform actions, hold data, and collaborate with other objects.
๐ง Analogy
A car on the road: it drives, turns, plays musicโthis is the active life phase.
We interact with it via methods, access properties, and pass it around.
๐ Example:
class Car {
String model;
Car(String model) {
this.model = model;
}
void drive() {
System.out.println(model + " is driving...");
}
}
Car c = new Car("Tesla");
c.drive(); // Tesla is driving...
๐๏ธ Stage 3: Object Eligible for Garbage Collection (Old Age)
๐ What is Garbage Collection?
Java uses automatic garbage collection we donโt manually free memory. Instead, when an object is no longer referenced, it becomes eligible for GC (garbage collection).
GC = Janitor that cleans up unused objects from the heap.
๐ง When Does an Object Become Eligible for Garbage Collection ?
When no variable points to it anymore.
Car c = new Car("Ford");
c = null; // Now the Ford object is unreachable
OR:
Car c1 = new Car("Ford");
Car c2 = new Car("Tesla");
c1 = c2; // The "Ford" object is no longer referenced
โฐ๏ธ Stage 4: Object Finalization (Before Death)
โ Deprecated: finalize()
method
Java earlier allowed us to override the finalize()
method as a โlast chanceโ to clean up before the object is collected:
protected void finalize() throws Throwable {
System.out.println("Object is being garbage collected");
}
โ ๏ธ But finalize()
has been deprecated since Java 9 and removed in Java 18
Why? Because:
- Itโs unpredictable
- It may never be called
- It delays GC
โ
Modern Alternatives: AutoCloseable
& try-with-resources
If our object holds external resources (like files, sockets), we shouldnโt wait for GCโinstead close them ourselves using AutoCloseable
.
๐ Example:
class MyResource implements AutoCloseable {
public void use() {
System.out.println("Using resource...");
}
public void close() {
System.out.println("Resource closed.");
}
}
try (MyResource res = new MyResource()) {
res.use();
}
// Output:
// Using resource...
// Resource closed.
We should use this pattern if we need deterministic cleanup.
๐ง 2. Lifecycle Recap
Letโs summarize the full lifecycle in human-like terms:
Stage | Java Equivalent | Real-World Analogy |
---|---|---|
Born | new keyword + constructor |
Car built in factory |
Alive | Object is in use | Car driving on the road |
Abandoned | All references removed | Car left in a junkyard |
Garbage Collected | GC picks up and frees memory | Car scrapped and recycled |
Final Words | finalize() (deprecated) or close() |
Saying goodbye or cleanup |
๐ ๏ธ Behind the Scenes: How GC Works (High-Level)
- Mark-and-Sweep: Marks reachable objects, then deletes unreachable ones.
- Stop-the-world: GC can pause all threads temporarily.
-
Generational GC:
- Young Generation (new objects)
- Old Generation (long-living objects)
- PermGen/Metaspace (for class metadata)
We donโt need to micromanage memory, but understanding this helps us:
- Avoid memory leaks
- Use
try-with-resources
correctly - Write memory-efficient applications
โ Tips for Object Lifecycle Management
- Avoid memory leaks by releasing references when done.
- Use weak references for cache-like behavior.
- Use
try-with-resources
for managing file/DB resources. - Avoid overriding
finalize()
โ itโs legacy. - Understand escape analysis if weโre tuning performance (advanced).
๐ง 3. JVM Memory Management: What we as Java Developerโs Must Know
The Java Virtual Machine (JVM) is like the engine behind every Java program. Understanding how it manages memory helps us avoid issues like:
- Memory leaks
- StackOverflowErrors
- OutOfMemoryErrors
- Inefficient object usage
๐ฆ JVM Memory Areas (Simplified)
When a Java program runs, the JVM divides memory into distinct regions:
๐๏ธ 1. Stack โ Short-lived & Thread-specific
- Stores method calls, local variables, and reference copies.
- One stack per thread.
- Memory is allocated/deallocated automatically as methods are called/returned.
- Faster than heap.
๐ Think of it like a stack of platesโlast in, first out.
๐ Stack Example:
public void compute() {
int a = 10; // stored in stack
String name = "Bob"; // reference stored in stack, object in heap
}
๐งบ 2. Heap โ Where Objects Live
- Stores all Java objects and arrays.
- Shared across all threads.
- Garbage-collected automatically.
๐ Think of it like a big object warehouse.
๐ Heap Example:
Person p = new Person("Alice");
// 'p' is on stack, but new Person is in heap
๐ง 3. Method Area / Metaspace
- Stores class metadata: class names, method definitions, constant pools, etc.
- Used to be called PermGen (before Java 8), now itโs Metaspace.
๐ ๏ธ 4. PC Register & Native Method Stack
- Internal machinery for bytecode execution.
- Mostly useful for JVM engineers.
๐ How Memory is Allocated
public void createPerson() {
Person p = new Person("John");
}
-
Stack:
- method
createPerson()
call - reference
p
- method
-
Heap:
Person
object with field"John"
When the method ends:
- Stack memory is cleaned up automatically
- Heap object remains until no references โ then garbage collected
โ๏ธ Heap vs Stack โ Comparison Table
Feature | Stack | Heap |
---|---|---|
Scope | Method-local | Application-wide |
Lifetime | Until method ends | Until GC cleans it |
Speed | Very fast | Slower |
Access | LIFO (Last In First Out) | Random |
Thread Safety | Thread-local | Shared across threads |
Stores | Primitives, references | Objects, arrays |
๐ 4. Escape Analysis โ Optimize Object Allocation
Java 6+ JVMs are smart. They use escape analysis to decide where to allocate objects: stack or heap.
๐ง What is Escape Analysis?
Determines whether an object โescapesโ the method or thread where it was created.
If an object:
- โ Does NOT escape โ JVM can allocate it on the stack (faster)
- โ Does escape โ JVM allocates on heap (slower, but persistent)
๐ Example: Does NOT escape
public int calculate() {
Point p = new Point(5, 10);
return p.x + p.y;
}
- The object
p
is used only in this method โ may be stack-allocated.
๐ Example: Escapes to outside
public Point createPoint() {
return new Point(1, 2);
}
- Object escapes via the return statement โ must go to heap.
๐ก Why Escape Analysis Matters
- Reduces GC pressure by avoiding heap allocation
- Improves performance via stack allocation and scalar replacement
- Enabled by default in modern JVMs (
-XX:+DoEscapeAnalysis
)
โ ๏ธ We canโt control it explicitlyโbut knowing it helps us to write cleaner methods with better optimization opportunities.
๐งผ 5. Garbage Collection โ How JVM Cleans the Heap
GC is a background process that:
- Finds unreachable objects
- Frees their memory
- Reclaims heap space
๐ GC Generations (Simplified):
Generation | Description | Frequency |
---|---|---|
Young Gen | New objects | Collected often |
Old Gen | Long-lived objects | Collected less often |
Survivor Spaces | Transition area between generations | Internal |
๐ ๏ธ GC Algorithms (Java HotSpot):
- Serial GC: Best for small apps (single-threaded)
- Parallel GC: Good for throughput
- G1 GC (default in Java 9+): Balanced, low-pause collector
- ZGC, Shenandoah: Ultra-low latency, large heaps (JDK 11+)
We can configure GC with JVM flags like:
-XX:+UseG1GC
-XX:+UseZGC
๐ง 6. Summary: Java Memory & Object Lifecycle
Step | Involves | Memory Area |
---|---|---|
Object creation | new + constructor |
Heap |
Method call | Parameters + local variables | Stack |
Object use | References to heap | Stack + Heap |
Object forgotten | Reference removed or goes out of scope | โ |
Object destroyed | GC removes unreachable objects | Heap |
โ 7. Tips for Java Memory Efficiency
- Keep methods short and focused โ enables escape analysis
- Use local variables where possible โ stack is faster
- Avoid unnecessary object creation โ reuse when possible
- Use
try-with-resources
โ ensures deterministic cleanup -
Monitor with tools:
jconsole
,VisualVM
,Java Mission Control