How to get full stack of StackOverflowError

The JVM has an artificial limit of 1024 entries that you can have in the stack trace of an Exception or Error, probably to save memory when it occurs (since the VM has to allocate memory to store the stack trace).

Fortunately, there is a flag that allows to increase this limit. Just run your program with the following argument:

-XX:MaxJavaStackTraceDepth=1000000

This will print up to 1 million entries of your stack trace, which should be more than enough. It is also possible to set this value at 0 to set the number of entries as unlimited.

This list of non-standard JVM options gives more details:

Max. no. of lines in the stack trace for Java exceptions (0 means
all). With Java > 1.6, value 0 really means 0. value -1 or any
negative number must be specified to print all the stack (tested with
1.6.0_22, 1.7.0 on Windows). With Java <= 1.5, value 0 means everything, JVM chokes on negative number (tested with 1.5.0_22 on
Windows).

Running the sample of the question with this flag gives the following result:

Exception in thread "main" java.lang.StackOverflowError
    at Overflow.<init>(Overflow.java:3)
    at Overflow.<init>(Overflow.java:4)
    at Overflow.<init>(Overflow.java:4)
    at Overflow.<init>(Overflow.java:4)
(more than ten thousand lines later:)
    at Overflow.<init>(Overflow.java:4)
    at Overflow.<init>(Overflow.java:4)
    at Overflow.a(Overflow.java:7)
    at Overflow.main(Overflow.java:10)

This way, you can find the original callers of the code that threw the Error, even if the actual stack trace is more than 1024 lines long.

If you can not use that option, there is still another way, if you are in a recursive function like this, and if you can modify it. If you add the following try-catch:

public Overflow() {
    try {
        new Overflow();
    }
    catch(StackOverflowError e) {
        StackTraceElement[] stackTrace = e.getStackTrace();
        // if the stack trace length is at  the limit , throw a new StackOverflowError, which will have one entry less in it.
        if (stackTrace.length == 1024) {
            throw new StackOverflowError();
        }
        throw e;  // if it is small enough, just rethrow it.
    }
}

Essentially, this will create and throw a new StackOverflowError, discarding the last entry because each one will be sent one level up compared to the previous one (this can take a few seconds, because all these Errors have to be created). When the stack trace will be reduced to 1023 elements, it is simply rethrown.

Ultimately this will print the 1023 lines at the bottom of the stack trace, which is not the complete stack trace, but is probably the most useful part of it.

Leave a Comment