Skip to Content
Course content

104: Memory Areas: Heap, Stack, and Metaspace

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Where does my data actually go when I create an object?

This is the classic "Stack vs. Heap" question. The simplest way to think about it is: the Stack is for execution and local references, while the Heap is for the actual data.

Imagine you're writing a method to process a customer's order. Look at this snippet:

public void processOrder() {
    int orderId = 101; 
    Customer customer = new Customer("Jane Doe");
}

Here is what's happening under the hood: The orderId is a primitive int, so it lives directly on the Stack. It's fast, it's local, and it disappears the moment the method finishes. But the Customer object? That's a different story. The variable customer is just a reference (essentially a memory address) that lives on the Stack, but the actual Customer object—the one holding the string "Jane Doe"—is allocated on the Heap.

I like to describe the Heap as a big, messy warehouse. Any time you use the new keyword, you're asking Java to find a spot in that warehouse to store your object. The Stack is more like your immediate workbench; it's organized, tiny, and only holds what you're working on right now.

Wait, what exactly is the Metaspace?

You might see older tutorials talking about "PermGen" (Permanent Generation). Forget about that; it was replaced in Java 8. Now we have Metaspace.

If the Heap is where your objects live, the Metaspace is where the blueprint for those objects lives. It stores class metadata, method definitions, and the constant pool. For instance, if you have 10,000 Customer objects on the Heap, you still only have one Customer.class definition in the Metaspace. It tells the JVM, "Okay, every Customer object should have a name string and an ID integer."

The big difference here is that Metaspace isn't part of the Heap; it uses native memory (RAM provided by the OS). In the old PermGen days, we'd often hit a hard limit and crash with an OutOfMemoryError: PermGen space. Metaspace is much more flexible because it can grow automatically, though I've still seen it crash in environments where someone is dynamically generating thousands of classes at runtime using bytecode libraries.

Why do some crashes say 'StackOverflow' and others say 'OutOfMemory'?

It all comes down to which "bucket" you've filled up. The Stack is very small and has a fixed size per thread. The Heap is huge and shared across the whole application.

You'll hit a StackOverflowError when you push too many "frames" onto the stack. This almost always happens during infinite recursion. I've seen juniors do this when trying to traverse a file directory or a tree structure without a proper exit condition:

public void recursiveCrash() {
    recursiveCrash(); // No exit condition!
}

In this case, Java keeps adding a new frame for recursiveCrash() on top of the previous one until the Stack simply runs out of room. It doesn't matter if you have 64GB of RAM; the Stack size is usually just a few megabytes.

An OutOfMemoryError (OOM), however, happens when the Heap is full and the Garbage Collector (GC) can't find anything to delete to make room for new objects. This usually happens if you're hoarding data in a static list or creating objects in a loop faster than the GC can clean them up:

List<byte[]> leak = new ArrayList<>();
while (true) {
    leak.add(new byte[1024 * 1024]); // Adding 1MB chunks forever
}

One is a "too many calls" problem (Stack); the other is a "too much stuff" problem (Heap).




📋 Practical Task

Exercise: Breaking the JVM: Stack vs. Heap

To truly understand these memory areas, you need to see them fail. Your task is to create a single Java class with two separate methods that demonstrate the two different memory crashes discussed in the lesson.

  • Method 1 (The Stack Buster): Create a method that calls itself recursively without a termination condition. This should trigger a java.lang.StackOverflowError.
  • Method 2 (The Heap Filler): Create a method that initializes a List and enters a while(true) loop, adding large objects (like large int[] arrays or byte[] buffers) to that list until the JVM runs out of heap space. This should trigger a java.lang.OutOfMemoryError: Java heap space.

Requirements:
1. Write the code in a class named MemoryCrashDemo.
2. In your main method, call only one of these methods at a time (comment out the other), as the first crash will stop the JVM entirely.
3. Observe the console output and identify exactly which error is thrown for each method.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.