LESSON 05 · BEGINNER4 min read

JVM Memory Anatomy: Stack Frames, Heap & Metaspace

Deconstruct JVM memory regions. Understand thread-private stacks, shared heap structures, Metaspace limits, and native method memory.

OpenJDK 21+ (LTS)Free to readModule 2 of 15
YOUR NEXT SMALL WINS

By the end, you’ll be able to…

  • Contrast thread-private memory (JVM Stack, PC Register) with thread-shared memory (Heap, Metaspace).
  • Trace stack frame allocation, primitive storage, and heap reference pointers.
  • Diagnose StackOverflowError vs OutOfMemoryError: Java heap space.

01Thread-Private vs Thread-Shared Memory

When the JVM executes an application, it divides physical RAM into distinct logical Runtime Data Areas. These areas are strictly partitioned based on thread ownership and lifetime.

Thread-Private memory areas are created when a thread starts and destroyed when the thread terminates. Each thread possesses its own Program Counter (PC) Register (tracking the current instruction offset) and its own JVM Stack. No thread can access the stack of another thread, guaranteeing local thread safety.

notes.txtPlain text
+---------------------------------------------------+|                JVM Memory Architecture            |+---------------------------------------------------+| [Thread 1 Stack]    [Thread 2 Stack]   [PC Regs]  || (Local variables, primitive values, references)   |+---------------------------------------------------+| [Shared Heap] (All Objects, Arrays, Records)      ||  Young Gen (Eden, S0, S1) -> Old Gen              |+---------------------------------------------------+| [Shared Metaspace] (Class metadata, Constant Pool)|+---------------------------------------------------+

02The Stack: LIFO Stack Frames

Each time a method is invoked, the JVM allocates a Stack Frame and pushes it onto the calling thread's stack. The stack frame stores primitive variables (int, double, boolean), method parameters, return addresses, and reference pointers pointing to objects in the heap.

Stack memory allocation is blazingly fast because allocation and deallocation merely require moving the stack pointer. When a method returns, its stack frame is instantly popped off. If recursive calls repeat without a base case, frames stack up until the thread-stack limit (-Xss, default 1MB) is reached, throwing a java.lang.StackOverflowError.

example.js☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

03The Heap and Metaspace

The Heap is the shared memory pool where all Java objects, arrays, and records reside. Regardless of where an object is instantiated (inside a method, static block, or lambda), the actual object payload is always allocated in the heap.

Metaspace holds class metadata, method bytecode, and constant pools. In older Java versions (Java 7 and earlier), this was called PermGen and was part of the contiguous heap. In modern Java, Metaspace is allocated out of native off-heap memory, expanding dynamically based on available system RAM unless bounded by -XX:MaxMetaspaceSize.

example.js☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

04Why This Matters in Production

Production crashes usually manifest as memory errors. Differentiating between StackOverflowError (infinite recursion or oversized stack depth) and OutOfMemoryError (heap exhaustion or Metaspace exhaustion) dictates whether you need to fix a recursive algorithm, tune GC heap sizing (-Xmx), or debug a ClassLoader leak.

Knowing that primitives reside directly on the stack while objects incur heap header overhead (~16 bytes on 64-bit JVMs with compressed OOPs) informs high-performance data structure choices.

05Production Architecture & Engineering Trade-Offs

From an operational reliability standpoint, configuring production JVM deployments requires continuous observation of runtime metrics and GC telemetry. In high-throughput distributed microservices, memory churn inside generational nurseries often creates hidden CPU overhead as threads repeatedly exhaust Thread-Local Allocation Buffers (TLABs). When a TLAB fills up, the HotSpot runtime must execute a synchronized fallback allocation directly into the global Eden space, introducing micro-stalls that compound under concurrent load.

Engineers diagnosing latency regressions must inspect Safepoint operations using HotSpot flags such as -XX:+PrintSafepointStatistics or modern Unified JVM Logging (-Xlog:safepoint=info). Many unexpected pause times attributed to garbage collection are actually caused by non-GC safepoint operations, including revoked biased locks, thread dumps, deoptimization traps, and class redefinition during dynamic agent instrumentation.

LET IT CLICK

The ideas worth keeping.

  • Stacks are thread-private and store frames; the Heap is thread-shared and stores all object instances.
  • Metaspace holds class metadata in native memory, governed by -XX:MaxMetaspaceSize.
  • Stack allocation is fast and automatic; Heap allocation requires garbage collection management.
TURN UNDERSTANDING INTO SOMETHING YOU CAN DO

Make it yours.

Type and test your code right here in the interactive workspace. Run your solution, check the output, and compare with the worked guide when ready.

01

Exercise 1: Simulating StackOverflowError

Write a program that safely catches StackOverflowError and prints the maximum recursive depth achieved before stack exhaustion.

your_turn_1.java☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.javaJava
public class DepthTest {    static int depth = 0;    public static void main(String[] args) {        try { test(); } catch (StackOverflowError e) {            System.out.println("Max depth reached: " + depth);        }    }    static void test() { depth++; test(); }}

Catching the error reveals the exact frame capacity of the thread stack under current -Xss configuration.

02

Exercise 2: Tuning Metaspace Bounds

What JVM flags set the initial and maximum Metaspace size to prevent unbounded native memory growth?

your_turn_2.java☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.javaJava
// JVM Metaspace tuning flags:// -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m

Setting MaxMetaspaceSize prevents rogue ClassLoader leaks from consuming all host operating system RAM.

A SMALL QUESTION. A USEFUL NEXT STEP.

What stayed with you?

Check the ideas while they’re fresh. Your answers stay in this page and feedback appears as you go.

A LITTLE ACTIVE RECALL0 / 3 answered
01Where are primitive variables declared inside a method body stored in JVM memory?
02What is the difference between PermGen (Java 7) and Metaspace (Java 8+)?
03What error occurs if an object allocation is requested but the Garbage Collector cannot free enough heap space?
⚡CODING CHALLENGE
🔒Required to Mark Lesson Complete

Exercise 1: Simulating StackOverflowError

Write a program that safely catches StackOverflowError and prints the maximum recursive depth achieved before stack exhaustion.

EXPECTED OUTPUT
Max depth reached: 0
Main.javaJava
Ctrl + ↵
Execution Console
Click "Run & Verify" (or press Ctrl + Enter) to test your code against the challenge.

Keep exploring.

The official references behind this lesson, when you want a second angle or the full details.

One lesson closer.

Reading is a start. Trying it yourself makes the connection.

Solve the hands-on coding challenge in the knowledge section to verify your code and unlock lesson completion.