Runtime Data Areas

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 5 min

TL;DR

The Runtime Data Areas are the memory architecture of the JVM. When the JVM starts, it divides the OS-allocated memory into 5 distinct zones:

  1. Method Area (Metaspace): Shared. Stores class-level data (bytecode, static variables).
  2. Heap Area: Shared. Stores all Objects and their instance variables.
  3. Stack Area: Per Thread. Stores local variables and method call frames.
  4. PC Register: Per Thread. Stores the address of the currently executing instruction.
  5. Native Method Stack: Per Thread. Stores method frames for native C/C++ code.

Concept

Understanding the Runtime Data Areas is critical for diagnosing OutOfMemoryErrors and StackOverflowErrors.

Shared Memory vs Thread-Local Memory

The Method Area and the Heap are shared globally across the entire JVM. If one thread modifies an object in the Heap, all other threads can see that modification (which is why synchronization is required to prevent Race Conditions).

The Stack, PC Register, and Native Method Stack are completely isolated. Every single time a new Thread is created, the JVM allocates a brand new Stack, a new PC Register, and a new Native Stack specifically for that thread. No thread can ever access another thread’s Stack memory. This makes local variables 100% thread-safe.

Examples

public class RuntimeDataAreaDemo {
    
    // 'staticCount' is stored in the METHOD AREA (Metaspace)
    static int staticCount = 0; 
    
    public static void main(String[] args) {
        // 'person' is a reference variable stored on the STACK
        // 'new Person()' creates an object stored on the HEAP
        Person person = new Person("Alice"); 
        
        person.doWork();
    }
}

class Person {
    // 'name' is an instance variable. It lives inside the Person object on the HEAP.
    String name; 
    
    public Person(String name) {
        this.name = name;
    }
    
    public void doWork() {
        // 'tasksCompleted' is a local variable. It lives entirely on the STACK.
        // It is destroyed the moment this method finishes.
        int tasksCompleted = 5; 
        System.out.println(name + " completed " + tasksCompleted + " tasks.");
    }
}

Interview Questions

Q: If two threads execute the same method simultaneously, do they share the method’s local variables?
A: No. Because local variables are stored on the Stack, and every thread has its own private Stack, each thread will create its own isolated copy of the local variables. They do not share them, which is why local variables are inherently thread-safe and do not require synchronized blocks.

Q: What causes a StackOverflowError?
A: A StackOverflowError occurs when a thread’s Stack memory is completely full. The Stack is composed of “Frames”. Every time a method is called, a new Frame (containing local variables) is pushed onto the Stack. If you write an infinite recursive method (public void recurse() { recurse(); }), it will push infinite frames onto the Stack until the allocated memory size is exceeded, causing the application to crash.