Java StackOverFlowError Causes & Solutions

Introduction

StackOverFlowError is one of the common JVM error. In this blog post, let’s learn inner mechanics of thread stacks, reasons that can trigger StackOverFlowError and potential solutions to address this error.

 

1. StackOverFlowError

To gain a deeper understanding of this exception, let’s review this simple program:

public class SimpleExample {

 public static void main(String args[]) {

  a();
 }

 public static void a() {

  int x = 0;
  b();
 }

 public static void b() {

  Car y = new Car();
  c();
 }

 public static void c() {

  float z = 0 f;
  System.out.println("Hello");
 }
}

This program is very simple with the following execution code:

  • main() method invoked first
  • main() method invokes a() method. Inside a() method integer variable ‘x’ is initialized to value 0.
  • a() method in turn invokes b() method. Inside b() method Car object constructed and assigned to variable ‘y’.
  • b() method in turn invokes c() method. Inside c() method float variable ‘z’ is initialized to value 0.

Now let’s review what happens behind the scenes when the above simple program executed. Each thread in the application has its own stack. Each stack has multiple stack frames. Thread adds the methods it’s executing, primitive data types, object pointers, return values to its stack frame in the sequence order in which they got executed.

thread-stack-frame

In step #1: main() method pushed into the application thread’s stack. Step #2: a() method pushed into application thread’s stack. In a() method, primitive data type ‘int’ is defined with value 0 and assigned to variable x. This information also pushed into the same stack frame. Note both data i.e. ‘0’ and variable ‘x’ pushed into thread’s stack frame.

In step #3: b() method pushed into thread’s stack. In b() method, ‘Car’ object created and assigned to variable ‘y’. A crucial point to note here is ‘Car’ object created in the heap and not in the thread’s stack. Only Car object’s reference i.e. y stored in the thread’s stack frame.

In step #4: c() method pushed into thread’s stack. In c() method, primitive data type ‘float’ is defined with value 0f and assigned to variable z. This information is also pushed into the same stack frame. Note both data i.e. ‘0f’ and variable ‘z’ is pushed into thread’s stack frame.

thread-stack-frame

 

2. StackOverFlowError Cause

As you can see thread’s stack is storing methods it’s executing, primitive data types, variables, object pointers and return values. All of these consume memory. If thread’s stack sizes grow beyond the allocated memory limit then StackOverflowError is thrown. Let’s look at the below buggy program, which will result in StackOverflowError:

public class SOFDemo {

 public static void a() {

  // Buggy line. It will cause method a() to be called infinite number of times.
  a();
 }

 public static void main(String args[]) {

  a();
 }
}

In this program main() method invokes a() method. a() method recursively calls itself. This implementation will cause a() method to be invoked an infinite number of times. In this circumstance, a() method got added to thread’s stack frame an infinite number of times. Thus, after a few thousand iterations thread’s stack size limit might exceeded. Once stack size limit exceeds, it will result in ‘StackOverflowError’:

Exception in thread "main" java.lang.StackOverflowError
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)

StackOverflowError

 

3. Solutions to StackOverflowError

There are a couple of strategies to address StackOverflowError.

3.1 Fix the Code

Because of a non-terminating recursive call (as shown in the above example), threads stack size can grow to a large size. In that circumstance, you must fix the source code which is causing recursive looping. When ‘StackOverflowError’ is thrown, it will print the stacktrace of the code that it was recursively executing. This code is a good pointer to start debugging and fixing the issue. In the above example it’s ‘a()’  method.

3.2 Increase Thread Stack Size (-Xss)

There might be a legitimate reason where a threads stack size needs an increment. Maybe thread has to execute a large number of methods or lot of local variables/created in the methods thread has been executing. In such circumstance, you can increase the thread’s stack size using the JVM argument: ‘-Xss’. Pass this argument when you start the application. Example:

-Xss2m

This will set the thread’s stack size to 2 Mb. It might bring a question, what is the default thread’s stack size? Default thread stack size varies based on your operating system, java version & vendor.

JVM version

Thread stack size

  Sparc 32-bit JVM   

512k

  Sparc 64-bit JVM  

1024k

  x86 Solaris/Linux 32-bit JVM

320K

  x86 Solaris/Linux 64-bit JVM

1024K

  Windows 32-bit JVM

320K

  Windows 64-bit JVM

1024K

 

Summary

In this article, we took a closer look at the StackOverflowError.We got an understanding of the cause of this error along with the options to fix this issue.