🎁 Give the #1 gift request of 2024... a ZTM membership gift card! 🎁

Stack Memory In Java: Beginner's Guide (With Code Examples)

Maaike van Putten
Maaike van Putten
hero image

Understanding memory management is often considered an advanced skill. However, I would argue that it’s a fundamental necessity if you want to become a proficient Java Developer.

Why?

Because understanding memory management is the cornerstone for achieving efficient execution of Java applications. It directly affects everything, from performance to error handling, and even debugging.

In this guide, I’m going to dive into Stack Memory in Java and break down some of the core components that make it work.

The more you understand it, the better your code will be, so let’s dive in!

Sidenote: Some of the topics in this post are a little complex, and hard to cover in a single article.

If you struggle to understand what I cover here, or simply want to learn more and dive into Java, then be sure to check out my complete Java programming course, or watch the first few videos for free.

learn java

You’ll learn Java coding from scratch, solidify your knowledge with exercises, build fun projects, and gain the skills you need to get hired as a Java Developer in 2024!

No prior programming knowledge is required. Just a willingness and enthusiasm to learn Java.

With that out of the way, let’s get into the guide!

What is Stack Memory in Java?

The Java Stack Memory is a key player in the execution of Java programs. It's where the method invocations and the local variables are stored and managed in a LIFO (Last In, First Out) manner.

java stack memory

More on this in a second…

Understanding Java Memory Management

Think of Java's memory model as a well-organized office, where every piece of information has its designated place, and there's a systematic way of storing and retrieving it.

stack

In Java, Stack Memory is a special region on the memory where the JVM (Java Virtual Machine) keeps track of method execution.

The primary role of Stack Memory is to manage and execute Java operations in real-time. It’s like a personal assistant to the program, keeping track of what's being done and what needs to be done next.

Each time a new method is called, Java creates a stack frame to keep it temporarily. This stack frame then contains specific details, such as the local variables of the method and the operations to be performed.

Stack Memory and the LIFO principle

Stack Memory operates on a LIFO (Last In, First Out) principle.

This means that the tasks are completed in a (Last In, First Out) manner, meaning the latest task to arrive is the first to be completed, so the one on top of the pile is completed first.

lifo

The stack memory is very orderly - once a task is done, it's then removed, leaving space for new tasks.

stack memory in java

Likewise, when a new method is called, a new block (called a stack frame) is added to the top of the stack. This process ensures that the most recent method call is always at the top, ready to be executed.

Heap Memory

Java's memory model can be divided into several areas, but for the purposes of this post, we're focusing on Stack memory. However, it would be remiss of me to not mention Heap memory, in regards to stack, and their differences.

The best way to understand this, is to imagine these as two different storage systems in our office analogy. Each system serves a specific purpose and has its own way of organizing information.

If Stack is like a stack of paper, with sheets being added and removed, then the Heap Memory is like a large storage room with shelves for storing various files (objects).

heap memory

The Heap is where Java stores all its dynamic data - meaning data that can grow or shrink during the execution of the application. Objects are created in the heap, and the references to these objects are stored in the stack memory.

The heap is larger and more flexible than the stack but also a bit slower to access.

To go back to our office analogy, every task could point to a certain number of an archive folder in the archive room. We would have to go into that room to see the details of the archive.

I'll cover this more in another post, but just so you get the general idea.

What is stored on the stack?

There are 3 major things stored on the stack:

1: Local Variables

These are the variables defined within methods. They only exist while the method is running and are not accessible outside it.

For example

public class Example {

	private int x; // NOT A LOCAL VARIABLE

	public void superUseful() {
		int y = 4; // local variable
	}

	}

2: Object References

While the objects themselves live in the Heap Memory, references or pointers to these objects are stored in the Stack Memory.

3: Method Calls

Information about the method calls. This can include how to return to the method that called the current method, and what to do next after the current method call.

method calls

Do you ever feel like Java needs some slightly different terminology? The more you use it though, the more it makes sense, I promise.

Java Stack Memory in Action

To understand how Java Stack Memory operates in real-world scenarios, let's walk through a simple Java program. This will help illustrate how Stack Memory is used during method invocation, execution, and return processes.

Method Invocation and Return Processes example

Imagine a Java program that calculates the sum of two numbers.

The main method calls a sum method, which does the calculation and then returns the result, like so:

Input:

public class Calculator {
    public static void main(String[] args) {
        int result = sum(5, 10);
        System.out.println("The sum is " + result);
    }

    public static int sum(int a, int b) {
        return a + b;
    }
}

Output:

The sum is 15

So let’s break this down by each section of code, so we can understand what is happening here.

When the program starts, the main method is called, and Java creates a stack frame in the Stack Memory for main.

TOP BLOCK

This frame then holds information like the method's local variables (args) and its state.

When the sum method is called, Java then creates another block on the stack, frame on top of the main frame for sum.

LIFO EXAMPLE

This new frame contains the local variables a and b and their values (5 and 10).

Once sum completes its task (calculating the sum), it returns the result (15) and its stack frame is popped off the Stack Memory. The control then returns to the main method, along with the result.

NEW TOP BLOCK

As you can see, the stack frames stay active as long as the method is running.

  • It holds all the necessary data for the method's execution, and the method that is being executed is on the top of the stack
  • As soon as the method finishes its task, its stack frame is removed (or popped off) from the Stack Memory

The implications of Stack Memory on Java performance

In Java programming, Stack Memory is not just a space for storing temporary data. In fact, its management and size can significantly impact the overall performance of an application.

Understanding these implications really helps you to write great Java code.

Threads and stack memory

The first thing to note is that each thread has its own stack.

(A thread is a path of execution through the program, and a concurrent program can have multiple threads created by the developer).

Also, the stack has a certain size that is specified at the start of the thread, and the size of the stack determines how many stack frames it can have. In other words, how deep your method calls can go.

lifo

In the previous example, we only went two levels deep, where we had the main and then the sum block, like so:

LIFO EXAMPLE

We could go deeper, but when we do, we add more blocks and use more space on the stack.

Why care? Well, if we go too deep and run out of space on the stack, we get a StackOverflowError.

stackoverflow

This doesn’t happen often, but it can still occur.

A common situation is when you use recursion and create an unintentional feedback loop, where a method is calling itself (and that method is calling itself).

For example

Let’s say that you wanted to calculate a factorial.

Note: This is good for illustrating the example, but this is not my preferred way of doing this:

public long calcFactorial(int n) {
    if (n <= 2) {
        return n;
    }
    return n * calcFactorial(n - 1);
}

As you can see, this method calls itself, which is fine at first. But, when the number of calls is bigger than the stack size, this will result in a StackOverflowError.

That is one of the reasons you should be cautious with recursive methods. It’s always a good practice to avoid unnecessary nested method calls and try to keep methods lean.

Sidenote: The stack size is something that can be altered with JVM tuning but that is a topic for another day.

Avoiding recursive methods is not the only way to optimize your stack memory. We can also reduce the number of local variables in your methods. More variables means more stack space usage, while fewer variables mean less usage!

However, it’s also important to write readable code, so when you’re not doing anything recursive you must either configure the JVM to have a very tiny stack or create a ridiculous amount of local variables to run out.

Did you get all that?

We’ve only just scratched the surface here, and haven’t even talked about Heap memory yet, so I hope your head isn’t spinning too much!

Stack memory is a little complex at first, but it does get easier the more you use it. Don’t skip this because it’s complex though. Understanding memory management is a vital part of learning how to be a better Java Developer.

I’ll have more on heap memory (and other topics) soon in another guide, but if you can’t wait until then, be sure to check out my complete Java programming course here, or watch the first few videos for free.

You’ll learn Java coding from scratch, solidify your knowledge with exercises, build fun projects, and gain the skills you need to get hired as a Java Developer in 2024!

No prior programming knowledge is required. Just a willingness and enthusiasm to learn Java.

And better still? When you join the course, not only do you have access to all the training content, but you can also ask questions of me and other Java Developers inside our private Discord channel, so you’ll never be stuck for long!

More from Zero To Mastery

12 Entry-Level Tech Jobs To Kick-Start Your New Career preview
12 Entry-Level Tech Jobs To Kick-Start Your New Career

Get your foot in the door with 4 roles that require zero experience, and 8 more that just require some self-taught education. ($5 + $6-figure salaries!)

Don’t be a Junior Developer: The Roadmap From Junior to Senior preview
Popular
Don’t be a Junior Developer: The Roadmap From Junior to Senior

Don’t sell yourself short. Seriously, don’t be a Junior Developer. This article outlines all the skills that you should learn if you want to get out of your Junior Developer role and get started on the path to becoming a Senior Developer.

Top 7 Soft Skills For Developers & How To Learn Them preview
Top 7 Soft Skills For Developers & How To Learn Them

Your technical skills will get you the interview. But soft skills will get you the job and advance your career. These are the top 7 soft skills all developers and technical people should learn and continue to work on.