⏱ 6 min read

🧠 Memory Management & Garbage Collection in Java

This guide explains how Java manages memory using Stack and Heap, how objects and references work, and how the JVM performs Garbage Collection (GC) to free unused objects.


Table of Contents

  1. Stack vs Heap
  2. Stack Memory
  3. Heap Memory
  4. String Pool
  5. Memory Allocation Example
  6. Object Reachability & GC
  7. Garbage Collection Algorithms
  8. Young Generation vs Old Generation
  9. GC Types
  10. Important Concepts

1. Stack vs Heap

Java memory is divided into two main regions:

Aspect Stack Heap
Stores Method frames, local variables, primitive values, object references Objects, arrays, String pool
Scope Per-thread (each thread has its own) Shared across all threads
Allocation LIFO order Dynamic (no strict order)
Deallocation Automatic when method ends Via Garbage Collector
Error when full StackOverflowError OutOfMemoryError
Speed Very fast Slower than stack

2. Stack Memory

Stack stores:

  • Method call frames (scope)
  • Local variables
  • Primitive values (int, double, boolean, etc.)
  • References to objects (the reference itself, not the object)

Key Behaviors:

βœ… LIFO (Last In, First Out) β†’ Variables exist only within their scope

βœ… Automatic cleanup β†’ When a method ends, its stack frame is popped and local variables are removed

⚠️ StackOverflowError β†’ Occurs if stack becomes full (common in infinite recursion)

Example:

void myMethod() {
    int x = 10;           // Stack: primitive stored here
    Person p = new Person();  // Stack: reference stored here
}
// When myMethod() ends β†’ stack frame is popped β†’ x & p reference removed

3. Heap Memory

Heap stores:

  • Objects created using new keyword
  • Arrays
  • String pool (String interned values)

Key Characteristics:

βœ… Shared across threads β†’ All threads can access heap objects

βœ… Garbage collected β†’ Objects freed when no longer referenced

⚠️ OutOfMemoryError β†’ Occurs if heap becomes full

Example:

Person p = new Person();  // Reference 'p' in stack, object in heap
String s = "Hello";       // Literal "Hello" in String pool (heap)

4. String Pool

String literals are stored in a special area called the String Constant Pool (inside heap).

String s1 = "Memory";      // Created in String pool
String s2 = "Memory";      // Points to SAME object in pool
String s3 = new String("Memory");  // NEW object in heap (not in pool)

System.out.println(s1 == s2);  // true (same reference)
System.out.println(s1 == s3);  // false (different objects)

5. Memory Allocation Example

Code:

int primitiveVar = 10;
Person personObj = new Person();
String stringLiteral = "Memory";
MemoryManagement memObj = new MemoryManagement();
memObj.memoryManagementTest(personObj);

UML Class Diagram:

Memory Management UML Diagram

Memory Layout Diagram:

Stack vs Heap Memory Diagram

PlantUML Generated Diagram:

Stack vs Heap Memory Diagram

What Happens in Memory:

Variable Storage Location Details
primitiveVar = 10 Stack Primitive value stored directly
personObj Stack β†’ Heap Reference in stack, object in heap
stringLiteral = "Memory" String Pool Literal stored in pool (heap area)
memObj Stack β†’ Heap Reference in stack, object in heap

When memoryManagementTest() ends:

  • Its local variables’ references are removed from stack
  • Heap objects may become unreferenced
  • Garbage Collector later cleans up unreachable objects

6. Object Reachability & GC

When Does an Object Become Garbage Collectable?

An object is eligible for garbage collection when it becomes unreachable from GC roots.

Common Ways Objects Become Unreachable:

βœ… Assigning to null

Person obj = new Person();
obj = null;  // Object becomes unreachable

βœ… Reassignment

Person obj1 = new Person();
Person obj2 = new Person();
obj1 = obj2;  // Old obj1 becomes unreachable (eligible for GC)

βœ… Method scope ends

void test() {
    Person obj = new Person();
}  // When test() ends β†’ reference removed β†’ object may become unreachable

7. Garbage Collection Algorithms

Mark β†’ Sweep β†’ Compact

The JVM performs garbage collection in three main steps:

Step 1: Mark

  • Identifies all reachable objects from GC Roots
  • Marks them as β€œlive”

Step 2: Sweep

  • Deallocates unmarked (unreachable) objects
  • Frees heap memory

Step 3: Compaction

  • Moves live objects together to reduce fragmentation
  • Creates contiguous free space

GC Roots (What Keeps Objects Alive):

Objects are considered alive if reachable from:

  • Local variables in active threads
  • Static variables
  • Class references
  • Thread objects

8. Young Generation vs Old Generation

Heap Structure:

The JVM heap is divided into generations:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Young Generation        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Eden       β”‚  Survivor (S0,S1)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         ↓ (promotion)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      Old / Tenured Generation    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         
Metaspace (Non-Heap) - Class metadata

Minor GC (Young Generation):

βœ… Runs frequently and quickly

βœ… Cleans up short-lived objects in Eden space

βœ… Moves surviving objects between Survivor spaces (S0 ↔ S1)

βœ… Tracks object age (how many GC cycles survived)

Promotion to Old Generation:

When an object’s age exceeds threshold (typically 8):

  • Object promoted from Young β†’ Old generation
  • Reduces Young generation size

Major/Full GC (Old Generation):

βœ… Runs less frequently but heavier cleanup

βœ… Higher pause time (application stops)

βœ… Cleans up old long-lived objects

Metaspace:

βœ… Stores class metadata and static information

βœ… Not part of heap (non-heap memory)

βœ… Replaced PermGen in Java 8+


9. GC Types

Different garbage collectors with different trade-offs:

Serial GC

  • Single-threaded
  • Stop-the-world pauses
  • Best for: Small applications, limited CPU

Parallel GC (Default in Java 8)

  • Multiple GC threads
  • Improved throughput
  • Best for: Multi-core systems, server applications

CMS (Concurrent Mark Sweep)

  • Reduced stop-the-world time
  • Attempts concurrent work with application
  • Not fully pause-free
  • Best for: Low-latency applications

G1 GC (Garbage First)

  • Balances throughput and latency
  • Includes automatic compaction
  • Aims to limit pause time
  • Best for: Large heaps, modern systems

10. Important Concepts

Stop-The-World (STW)

Many GC phases pause application threads:

  • Serial GC pauses more
  • G1 GC tries to limit pause time
  • Longer pauses = noticeable application lag

Java Memory Leaks

Even with automatic GC, leaks can occur when:

  • References unintentionally kept alive
  • Static maps growing unbounded
  • Event listeners not removed
  • Thread-local variables not cleaned up

Definition: A memory leak is when an object is no longer needed but remains reachable, preventing GC from freeing it.

System.gc() is Optional

System.gc();  // Just a SUGGESTION, not a command
  • JVM may or may not run GC
  • GC timing depends on memory pressure and implementation
  • Rely on JVM to manage GC automatically

Weak vs Soft References

Strong Reference (Default)

Person p = new Person();  // GC won't delete while reachable

Weak Reference

WeakReference<Person> wp = new WeakReference<>(new Person());
// GC can collect immediately during next GC cycle

Soft Reference

SoftReference<Person> sp = new SoftReference<>(new Person());
// GC collects only when memory is desperately needed (cache scenarios)

Quick Summary & Revision

Concept Key Points
Stack Per-thread, LIFO, stores primitives & references, fast deallocation
Heap Shared, stores objects, freed by GC, slower allocation
String Pool Special heap area for literal strings
Young Gen Eden + Survivor spaces, frequent minor GC
Old Gen Long-lived objects, major GC less frequent
Mark-Sweep-Compact GC identifies reachable objects, removes unreachable, compacts memory
Stop-The-World Application pauses during GC phases
Memory Leak Object unreferenced but still reachable = GC can’t clean
Strong Reference Keeps object alive
Weak Reference GC can collect anytime
Soft Reference GC collects under memory pressure

← Back to Core Java ← Java Home 🏠 Home