Do you find it confusing when you read documentation full of terms like ‘stack’ and ‘heap’? Both are critical areas of the JVM memory, but what are they and in what ways are they different?
This article looks at Java heap vs stack memory, discusses how they are used, and illustrates the difference with a worked example.
JVM Memory Overview
The JVM has several memory pools, each with a separate purpose.
We can visualize it like this:

Fig: JVM Memory Model
The heap is managed by the JVM, whereas the other memory pools reside in native memory. Each running thread has a stack, which is held in the Threads pool within native memory. If you’d like to learn more about the JVM memory model, I recommend this video: JVM Explained in 10 Minutes.
What is the Heap?
The heap is a central storage area shared by all classes that make up an application.
Before looking at what’s stored in the heap, let’s differentiate between Java primitive variables and object variables.
Primitives are the eight data types that make up the Java language: byte, short, int, long, float, double, char and boolean.
Objects are instances created from a Java class by using the keyword new, for example, String var1 = new String(). This includes arrays, since they are also created with the keyword new.
The heap stores:
- All objects, regardless of how and where they are defined;
- Primitives defined as instance variables, i.e. defined within the class but outside of any of the methods that make up the class.
It does not store Java primitives that are defined within a method (local variables). As we’ll see later, these are held in the stack.
The heap is split into regions in order to optimize garbage collection (GC). New objects are created in the Young Generation (YG). The developers of the JVM have noted that the majority of objects are short-lived, for example, variables needed for the duration of a single transaction. By keeping the YG fairly small, it can be cleaned very quickly, and effectively dispose of the majority of garbage. Variables that survive several cycles of GC are moved to the Old Generation (OG), also known as the Tenured Generation. The OG is cleaned less frequently.
The YG is further subdivided. Eden space holds newly-created objects. If they survive long enough without becoming garbage, they’re moved to the next stage – S0 or S1 – before being finally promoted to the OG. S0 and S1 are survivor spaces, and they’re used alternately.
What is Stack?
In computer science, a stack is a data structure where new items are added (pushed) to the top, and only the newest item can be accessed. This is known as a LIFO (Last in First Out) structure. To access the next layer, the topmost item must be removed, or ‘popped’ from the stack.
In programming, stacks are used to retain context when methods call other methods in what may be a long chain of control. The stack area in the JVM stores the context for each active (uncompleted) method.
Each thread has its own stack space within the Threads area of memory. This contains its program counter (PC), which is the address of the next instruction to be executed. It also contains a frame for each active method, arranged in a stack structure. Each frame contains:
- Local variables. If they are primitives, they are held directly in the stack frame. If they are objects, they are stored in the heap, but the stack frame stores a reference pointer to the actual object.
- The operand stack. This holds intermediate results and partial computations.
- The method’s return address
- A pointer to the method’s area in the constant pool
- Pointers to exception handlers
We can visualize it like this:

Fig: JVM Stack Space
Java Heap vs Stack Memory
As we’ve seen, the heap is a central storage area used by all classes and threads in the application. The stack is used to store the context of active methods for each thread. It also stores some data, namely, primitive local variables, and pointers to the location of object local variables in the heap.
If the heap runs out of space, the application will throw an Out of Memory error. If the stack has no more room to store new frames, this will result in a Stack Overflow Error.
Let’s look at a worked example of how both the heap and the stack are used by an actual program.
We’ll run through exactly what happens when the code below is run.
import java.util.ArrayList;
public class VariablesDemo {
// Instance Variables
// ==================
int classVar0;
String classVar1 = new String();
public VariablesDemo() {
// Local Variables for the constructor
// ===================================
int constructorVar0;
char[] constructorVar1 = new char[20];
method1();
}
public void method1() {
// Local Variables for the Method 1
// ================================
byte method1Var0;
Integer method1Var1 = new Integer(0);
method2();
}
public void method2() {
// Local Variables for the Method 1
// ================================
long method2Var0;
ArrayList method2Var1 = new ArrayList();
}
}
Step 1: The class has been created. The instance variables are stored in the heap. Nothing has yet been added to the stack.

Fig: Heap and Stack Contents at Step 1
Step 2: The constructor VariablesDemo is called. A stack frame is created for it in the stack. The variable constructorVar0 is a primitive local variable, so it is stored within the stack frame. The variable constructorVar1 is an object. It’s stored in the heap, and a reference pointing to it is stored in the stack frame.

Fig: Heap and Stack Contents at Step 2
Step 3: The method method1 is called. A frame is added to the stack for it, which contains the primitive local variable method1Var0 and a pointer to the object variable method1Var1. Again, the actual object method1Var1 is stored on the heap.

Fig: Heap and Stack Contents at Step 3
Step 4: The method method2 is called, and a frame for it is added to the stack. The frame contains the primitive local variable method2Var0 and a pointer to the object variable method2Var1. The object method2Var1 is stored on the heap.

Fig: Heap and Stack Contents at Step 4
Step 5: Method 2 completes. Its frame is removed from the stack. Since method2Var1 no longer has any references pointing to it, it becomes eligible for GC.

Fig: Heap and Stack Contents at Step 5
Step 6: Method 1 completes. Its frame is removed from the stack. Since method1Var1 no longer has any references pointing to it, it becomes eligible for GC.

Fig: Heap and Stack Contents at Step 6
Step 7: The constructor VariablesDemo completes. Its frame is removed from the stack. Since constructorVar1 no longer has any references pointing to it, it becomes eligible for GC.

Fig: Heap and Stack Contents at Step 7
Step 8: On the next GC cycle, the three variables that are eligible for garbage collection are removed from the heap.

Fig: Heap and Stack Contents at Step 8
Conclusion
Briefly, when we compare Java heap vs stack memory, the following points are relevant:
- The heap is a common storage area used by all threads and all classes within a program. It stores any objects created by the program, and also stores Java primitives defined as instance variables.
- The stack is a structure created within the Threads area of memory. Its purpose is to retain context for each active method within each thread. Local variables defined as primitives are stored in the stack, whereas local object variables are stored in the heap. The stack stores pointers to each local object variable.
- The heap is an area of JVM-managed memory. The stack is a structure within the Threads area, which is in native memory.
- The heap is cleaned regularly by the GC, whereas a stack frame is popped from the stack when a method completes, freeing up the space it occupied.
Each has its own purpose and its own method of organization. A good understanding of the stack and the heap helps you to plan memory usage more efficiently, as well as being useful for troubleshooting and performance tuning.
Quick Visual Recap
Here’s a concise infographic from our LinkedIn post that highlights the key differences between Heap and Stack memory in Java.
