Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

The call stack is a crucial data structure that manages method execution and variable scope in Java. The stack depth, or the number of active method calls it can hold, is an important consideration when dealing with recursive functions or deep call chains.

In this tutorial, we’ll explore techniques to determine the maximum depth of the Java call stack.

2. Understanding Java Call Stack

The Java call stacks follow a Last In, First Out (LIFO) structure. When a method is invoked, a new stack frame is pushed onto the top of the stack containing information like parameters, local variables, and return address. Once the method completes execution, its stack is popped off the stack.

The total stack size allocated to each thread determines the amount of data its call stack can hold. The default stack size varies by JVM implementation, but it’s typically around 1MB for a standard JVM.

We can check the default stack size for our JVM using the -XX:+PrintFlagsFinal parameter:

$ java -XX:+PrintFlagsFinal -version | grep ThreadStackSize

With a 1MB stack, we can make approximately 10000 to 20000 method calls before hitting the maximum depth, assuming each stack frame uses around 100 bytes. The key point is that the stack size limits how deep the call stack can grow.

3. Maximum Depth of Java Call Stack

Here’s an example that intentionally overflows the call stack to determine its maximum depth:

public class RecursiveCallStackOverflow {
    static int depth = 0;
   
    private static void recursiveStackOverflow() {
        depth++;
        recursiveStackOverflow();
    }
    
    public static void main(String[] args) {
        try {
            recursiveStackOverflow();
        } catch (StackOverflowError e) {
            System.out.println("Maximum depth of the call stack is " + depth);
        }
    }
}

The recursiveStackOverflow() simply increments a counter and calls itself recursively until the stack overflows. By catching the resulting error, we can print out the depth reached.

When we test this on a standard JVM, here’s the output:

Maximum depth of the call stack is 21792

Let’s check the default stack size of our JVM using the -XX:+PrintFlagsFinal parameter:

$ java -XX:+PrintFlagsFinal -version | grep ThreadStackSize

Here’s the default thread stack size of our JVM:

intx ThreadStackSize = 1024 

By default, the JVM allocates a 1MB thread stack size.

We can increase the maximum depth by allocating more stack space for the thread using the -Xss JVM parameter:

$ java -Xss2m RecursiveCallStackOverflow

With a 2MB thread stack size, here’s the output:

Maximum depth of the call stack is 49522

Doubling the stack size allowed the depth to increase proportionally.

4. Conclusion

In this article, we learned how to get the maximum depth of the stack call by recursively calling a method. Additionally, we saw that JVM has a default stack size. It can be increased by allocating more memory space to increase the depth of the stack call.

As always, the complete source code for the example is available over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
2 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Comments are closed on this article!