Overview

StackOverflowError is one error which every java developer comes across as it is one of the most common runtime error a java developer can encounter. In this post, we will get to know about StackOverflowError by looking at code example, understand stack frames and how to handle StackOverflowError in Java.

Stack frames, and how StackoverflowError occurs

Let us start with the basics when a method is called a new stack frame is created on the call stack. All function parameters and local variables are distributed on the stack. The object lives on the heap and a variable on the stack references that object on the heap.

public void foo() {
	int i = 0;
	int c = 0;
	User userObject = new User();
}
Stack and Heap
Code on Stack and Heap

If you look at the above code snippet and accompanying diagram, you should be able to understand what happens on each line in the code snippet. When a function call is invoked, a stack frame is allocated on the call stack. It contains function parameters, local variables and return address of the method. When the function returns, the program continues execution from the return address. If there is no space available on the call stack for a new stack frame, then the java.lang.StackOverflowError is thrown by the Java Virtual Machine (JVM).

When a StackOverflowError occurs java.lang.StackOverflowError, it is mainly because the stack space required by the program has exceeded in Java Virtual Machine (JVM) or the native stack size configured in the operating system is exhausted.

Note: StackoverFlowError are sometimes masked by Out of Memory exceptions, so by resolving the memory constraints the stack overflow exception can be resolved.

Handle StackoverFlowError

To handle StackoverFlowError, you should carefully inspect the stack trace to detect any repeating call patterns in your code. These indicate recursive calls to your code or function.

Some traits of recursion:

  1. Large thread stacks that appear to repeat
  2. An infinite loop that continuously spawns off threads
  3. Very large XML documents loaded into the Document Object Model (DOM)
  4. JSP or servlets calling itself (usually by executing forward or include to itself)
  5. Repeated calls in native functions

Below is an example class showing how recursion can cause `java.lang.StackOverflowError` if not implemented properly.

package com.aabingunz.stack.overflow.error;

public class StackoverFlowErrorTest {
    public static void main(String[] args) {
        StackoverFlowErrorTest.recursiveSop(1);
    }

    public static void recursiveSop(int num) {
        System.out.println("Number: " + num);
        if(num == 0)
            return;
        else
            recursiveSop(++num);
    }
}

Console Output

Number: 1
Number: 2

Number: 6278
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at java.io.PrintStream.write(PrintStream.java:482)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.write(PrintStream.java:527)
at java.io.PrintStream.print(PrintStream.java:669)
at java.io.PrintStream.println(PrintStream.java:806)
at com.aabingunz.stack.overflow.error.StackoverFlowErrorTest.recursiveSop(StackoverFlowErrorTest.java:9)
at com.aabingunz.stack.overflow.error.StackoverFlowErrorTest.recursiveSop(StackoverFlowErrorTest.java:13)
at com.aabingunz.stack.overflow.error.StackoverFlowErrorTest.recursiveSop(StackoverFlowErrorTest.java:13)
at com.aabingunz.stack.overflow.error.StackoverFlowErrorTest.recursiveSop(StackoverFlowErrorTest.java:13)

at com.aabingunz.stack.overflow.error.StackoverFlowErrorTest.recursiveSop(StackoverFlowErrorTest.java:13)
at com.aabingunz.stack.overflow.error.StackoverFlowErrorTest.recursiveSop(StackoverFlowErrorTest.java:13)

Do you see repeated calls in the stack trace? This is where we should examine and correct our code.

Note: Depending on the JVM’s initial configuration above stack trace will be thrown.

Ones detected, check your code for a terminating condition so that it can stop repeated calls to itself. If you have a terminating condition, then examine your code carefully to understand why recursion never terminates.

Check to see that at least one argument in your called function is modified, otherwise your terminating condition will be useless. The above code never ends because recursiveSop function is called with a value starting from 1 in increasing order, which will never satisfy the terminating condition is num == 0.

Even when your arguments are constantly changing in every function call, check that your function can handle enough recursive calls as the stack space can run out of memory before reaching your terminating condition.

If everything looks fine, then check to see if you are calling any library function, examine this library function and try to rule out the fact that it might cause a recursive call to your function.

Another important aspect to remember here is that the default thread stack size depends on the installed Java Virtual Machine (JVM), so your program may run perfectly fine on one environment but might throw a StackoverFlowError on another. You can try increasing the maximum thread stack size using the -Xss<size> flag.

In case of depleted native stack try increasing the initial native stack size using the -Xmso<size> flag. This is only for distributed platforms (AIX, Linux, Windows)

Note: <size> has the format, nn[k|m|g|K|M|G], such as -Xss512K

Conclusion

In this article we carefully looked at how a StackOverflowError occurs in Java using code examples and stack frames, how we can examine the code for repeated calls and fix on the terminating condition and how setting the initial and maximum thread stack size can handle StackOverflowError in Java.

References

Java Doc

Diagnosing a java.lang.StackOverflowError


Simon

I am a Fullstack developer and Consultant with an experience of 9+ years in the industry. I mainly work on Java, React, Javascript, NodeJs, Elasticsearch and Botpress.

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *