Java Memory Management 101: Stack Memory

Murat
5 min readDec 31, 2022

--

Applications require a certain amount of space (RAM) on a computer. Every time an object or variable is created within the application, it consumes additional RAM. Allocating enough memory to hold every declared value and execute each method would result in an unnecessarily large application.

To optimize the memory usage of an application, it is divided into smaller sections that require less memory and enable the application to run more efficiently. This helps to keep the overall memory requirements of the application lean and efficient.

The Java Virtual Machine (JVM) divides the memory into two sections: HEAP and STACK memory.

Before jumping into Stack memory let’s understand stack and how it works.

Let me first give you an real world example how stack works.

Think about pile of clean plates for serving dinner. When the customer is ready to be served, the waitress would take the top plate from the stack and bring it to the customer’s table.

The dishwasher would then wash the dirty dishes and add the clean ones to the top of the pile of clean plates, ready to be used again.

Stack in a Real Life

As you can see from the example, top of the plate is always waiting to be served first.

This approach is called Last in First Out, also known as LIFO.

Deep Dive Time to Stack Memory!

Stack memory is a special region of a computer’s memory that stores temporary variables and references used by each function, including the main() function. It is a “last in, first out” (LIFO) data structure that is managed and optimized by the CPU.

How it works?

A key to understanding the stack memory is that whenever a method is called, a new block is created on the top of the stack to store. When a function exits, all of its variables and references are popped off of the stack (and hence lost forever).

In Java, the stack memory is used to store local variables and reference variables. When a method is called, a new block is created on the top of the stack to store the method’s local variables and reference variables. When the method completes, the block is removed from the top of the stack.

The following code helps you to understand of how stack memory works.


class Wizard{
int age;
String wizardName;

public Wizard(int age, String wizardName) {
this.age= age;
this.wizardName= wizardName;
}
}

public class WizardDetail{
private static createWizard(int age, String wizardName) {
return new Wizard(age, wizardName);
}

public static void main(String[] args) {
int age= 13;
String name = "Harry Potter";
Wizard wizard= null;
wizard= createWizard(age, name);
}
}

Let’s analyze this step-by-step:

Allocation

  1. The main method is called and a block of memory is allocated on the stack for its local variables and method calls.
  2. The local variables age and reference variable name are created in the stack and assigned the values 13.
  3. The reference variable wizard is created in the stack.
  4. The createWizard method is called and a block of memory is allocated on the stack for its local variables and method calls.
  5. The local variables age and reference variable name are created in the stack and assigned the values 13.
  6. The reference variable wizard is created in the stack.
  7. The Wizard constructor is called block of memory is allocated on the stack for its local variables and method calls.
  8. The local variables age and reference variable name are created in the stack and assigned the values 13.
  9. The createWizard method returns a reference to the new Wizard object, which is assigned to the wizard variable in the main method.
  10. The reference variable this is created in the stack.

Deallocation

  1. The createWizard method's block of memory is freed up and returned to the stack.
  2. The main method’s block of memory is freed up and returned to the stack.

Don’t forget the the differences between reference variable and object itself. Reference variable only keeps reference value on it and it is stored in Stack memory. On the other hand, object itself is stored in Heap Memory (In this post, we did not mention the topic of heap memory). Wizard object is not stored on the Stack Memory. Only reference of Wizard is stored on Stack.

Let’s look at this example’s allocation in the diagram below:

Stack Memory Allocation Diagram

JVM stack is specific to each thread, meaning that each thread has its own separate stack. This allows multiple threads to execute concurrently, as each thread has its own set of method calls and local variables. This feature makes this space safe because the data can only be accessed by the owner thread.

Stack and Frame illustration with owner Thread

The other important thing to remember is that we receive the corresponding error Java.lang.StackOverFlowError by JVM, If the stack memory is filled completely.

Summary

In conclusion, stack memory is a vital part of Java programming. It is used to store local variables and references of objects, which are essential for the proper functioning of a Java program.

Understanding how stack memory works can help you write more efficient and effective code in Java. It is important to keep in mind that stack memory is organized in a LIFO structure and is only accessible within the method in which it is declared.

Additionally, it is important to understand the difference between stack memory and heap memory. I will explain the Heap Memory and differences between Heap and Stack memory in another articles to avoid making this post too long and losing your focus.

You can read my post about Heap Memory to continue memory management topic.

--

--