1. The Hook (The "Byte-Sized" Intro)
- In a Nutshell: JVM architecture has 3 main components: Class Loader (loads .class files), Runtime Data Areas (memory), Execution Engine (runs bytecode).
- Memory areas: Heap (objects, shared, GC target), Stack (method frames, thread-specific, local variables), Metaspace (class metadata, replaces PermGen), PC Registers (thread instruction pointer), Native Method Stack (JNI calls).
- Heap structure: Young Gen (Eden + 2 Survivors) + Old Gen.
- Key: Heap = shared + slow, Stack = thread-local + fast!
Think of city infrastructure. Class Loader = immigration (brings newcomers). Heap = residential area (houses/objects, cleaned by garbage truck/GC). Stack = office cubicles (worker-specific, temporary). Metaspace = city blueprints (building codes/class metadata). PC Register = GPS (tracks where you are)!
2. Conceptual Clarity (The "Simple" Tier)
💡 The Analogy
- Heap: Apartment complex (shared, managed, cleaned regularly)
- Stack: Personal desk (fast access, yours only, auto-cleared)
- Metaspace: Library (class definitions, rarely changes)
JVM Architecture
graph TD
A[JVM] --> B[Class Loader<br/>Subsystem]
A --> C[Runtime Data<br/>Areas]
A --> D[Execution<br/>Engine]
B --> B1[Bootstrap]
B --> B2[Extension]
B --> B3[Application]
C --> C1[Heap<br/>Shared]
C --> C2[Stack<br/>Per-thread]
C --> C3[Metaspace<br/>Shared]
C --> C4[PC Registers<br/>Per-thread]
D --> D1[Interpreter]
D --> D2[JIT Compiler]
D --> D3[Garbage<br/>Collector]
style C1 fill:#C2185B
style C2 fill:#2E7D32
style C3 fill:#F57C00
Heap Memory Structure
graph TD
A[Heap Memory] --> B[Young Generation]
A --> C[Old Generation<br/>Tenured]
B --> D[Eden Space<br/>New objects]
B --> E[Survivor 0<br/>S0]
B --> F[Survivor 1<br/>S1]
style D fill:#2E7D32
style E fill:#F57C00
style F fill:#F57C00
style C fill:#C2185B
3. Technical Mastery (The "Deep Dive")
Runtime Data Areas Comparison
| Area | Shared? | Stores | GC? | Size |
|---|---|---|---|---|
| Heap | ✅ Yes | Objects, arrays | ✅ Yes | -Xms/-Xmx |
| Stack | ❌ No (per-thread) | Local vars, frames | ❌ No | -Xss |
| Metaspace | ✅ Yes | Class metadata | ⚠️ Rare | -XX:MaxMetaspaceSize |
| PC Register | ❌ No (per-thread) | Next instruction | ❌ No | Small |
| Native Stack | ❌ No (per-thread) | JNI calls | ❌ No | Small |
4. Interactive & Applied Code
java
public class JVMMemoryDemo {
// Stored in METASPACE (class metadata)
static int staticVar = 100; // Value in HEAP (or Metaspace for primitives)
public static void main(String[] args) {
demonstrateHeap();
demonstrateStack();
demonstrateMetaspace();
}
// Heap vs Stack demonstration
static void demonstrateHeap() {
System.out.println("=== HEAP MEMORY ===");
// Objects go to HEAP
Person p1 = new Person("Alice"); // Object in HEAP
Person p2 = new Person("Bob"); // Another object in HEAP
// Arrays go to HEAP
int[] numbers = new int[1000]; // Array in HEAP
// String objects in HEAP (String pool)
String s1 = "Hello"; // String pool (HEAP)
String s2 = new String("World"); // Regular heap
System.out.println("Objects created in heap");
}
static void demonstrateStack() {
System.out.println("\n=== STACK MEMORY ===");
// Local variables in STACK
int x = 10; // Primitive in STACK
int y = 20; // Another primitive in STACK
// Reference in STACK, object in HEAP
Person p = new Person("Carol"); // 'p' (reference) in STACK
// Person object in HEAP
methodA(); // New frame pushed to stack
// Frame popped when method returns
}
static void methodA() {
int localVar = 5; // In this method's stack frame
methodB(); // Another frame pushed
}
static void methodB() {
int anotherVar = 10; // In this method's stack frame
// Frame popped when returning
}
// Metaspace demonstration
static void demonstrateMetaspace() {
System.out.println("\n=== METASPACE ===");
// Class metadata stored in METASPACE
Class<?> cls = Person.class;
System.out.println("Class name: " + cls.getName());
System.out.println("Methods: " + cls.getMethods().length);
// Static variables metadata in METASPACE
System.out.println("Static var: " + staticVar);
}
}
class Person {
String name; // Instance variable (in HEAP with object)
Person(String name) {
this.name = name;
}
}
// Stack Overflow demonstration
class StackOverflowDemo {
static int depth = 0;
static void recursiveMethod() {
depth++;
recursiveMethod(); // Infinite recursion → StackOverflowError
}
public static void main(String[] args) {
try {
recursiveMethod();
} catch (StackOverflowError e) {
System.out.println("Stack depth: " + depth);
}
}
}
// Memory monitoring
class MemoryMonitoringDemo {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println("=== JVM MEMORY ===");
System.out.println("Max Memory (Heap): " +
runtime.maxMemory() / 1024 / 1024 + " MB");
System.out.println("Total Memory: " +
runtime.totalMemory() / 1024 / 1024 + " MB");
System.out.println("Free Memory: " +
runtime.freeMemory() / 1024 / 1024 + " MB");
System.out.println("Used Memory: " +
(runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024 + " MB");
}
}5. The Comparison & Decision Layer
| Heap | Stack |
|---|---|
| Shared across threads | Thread-specific |
| Objects, arrays | Primitives, references, frames |
| Slower access | Faster access |
| GC managed | Auto-cleared on method return |
| Size: -Xms/-Xmx | Size: -Xss |
| OutOfMemoryError | StackOverflowError |
6. The "Interview Corner" (The Edge)
The "Killer" Interview Question: "Where are local variables stored? Heap or Stack?" Answer: It depends!
- Primitive local variables: STACK
- Object local variables: Reference in STACK, object in HEAP
java
void method() {
int x = 10; // ✅ STACK (primitive)
Person p = new Person(); // Reference 'p' in STACK
// Person object in HEAP
}
// After method returns:
// - Stack frame cleared (x and p reference gone)
// - Person object in heap (eligible for GC if no other refs)Pro-Tips:
- Young vs Old Gen:
text
Young Gen (Minor GC, frequent):
- Eden: New objects start here
- S0/S1: Survivors after GC
- Objects promoted to Old Gen after ~15 GC cycles
Old Gen (Major GC, infrequent):
- Long-lived objects
- Larger, slower GC- PermGen → Metaspace (Java 8+):
bash
# Old (Java 7): Fixed size, OutOfMemoryError: PermGen
-XX:PermSize=64m -XX:MaxPermSize=256m
# New (Java 8+): Native memory, grows dynamically
-XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=256m