-1

Why am I getting strange output in case of StackOverflowError ?

public class Hello{  
    public static void main(String args[]){  
        System.out.println(new Exception().getStackTrace().length);  
        m1();  
    }  
    public static void m1(){  
        m2();  
    }  
    public static void m2(){  
        try{  
            m1();  
        }catch(StackOverflowError err){  
            System.out.println(err.getStackTrace().length);  
        }  
    }  
}  

Output (a)-
        1
        102410241024102410241024102410241024

Output (b) -
        1024

Output (c)-
        1
        1024   

When the above code executes I am getting Output (a).But when I am commenting first line of main method I am getting Output (b).

I should be getting Output (c) when I am executing the above code by keeping the first line in main method uncommented

Why is 1024 getting printed so many times in Output (a)?

I was trying to find out default stack size by raising StackOverflowError and purposely catching it.I printed stack size before calling m1 method from main method.

  • I think the issue here is that your `catch` clause (which is catching a StackOverflowError) attempts to add 2 more entries to the stack. I'm surprised that the JVM executes any of that code, and suspect it's platform/implementation specific behavior. Maybe ther'es a "soft" cap before the heap actually overflows the stack and the difference between the soft and hard cap is the how many levels of "catch" you see there, but none of the methods actually complete, so the trailing carriage return isn't added by `println`. That's just a guess though -- you're in uncharted territory AFAIK. – Gus May 23 '18 at 20:20

2 Answers2

1

Suppose you have on your stack

m1 - > m2 - > m1 - > m2 - > m1 - > m2 - > m1 - > m2 - > m1 

and then stack overflow, then the error is caught with this stack:

m1 - > m2 - > m1 - > m2 - > m1 - > m2 - > m1 - > m2

and then another error is thrown because you call a method in your catch clause and then you catch with this stack:

m1 - > m2 - > m1 - > m2 - > m1 - > m2

and then another error is thrown and so on. This will continue until your catch clause no longer causes another error. Also note that when and how you get an error is dependent on when and how your methods are compiled by the JIT, which is unpredictable.

Sean F
  • 4,344
  • 16
  • 30
0

First of all, notice that it doesn't matter what you print for that behavior to occur, any print at all is enough.

With a print at the beginning: so, with some debugging I noticed that in method PrintStream.write(String s) there is a line textOut.flushBuffer() that fails unexpectedly. The result of that, basically, is that the requested String is added to the buffer, but the buffer is not flushed, and the new line is not added to the buffer, because it is a separate step and comes long after the point of invocation that failed. Then at the end, at the last print, this method completes successfully, so your String is printed to the console, along with all the previous ones, since they were waiting in a buffer (1024 multiple times).

Without the print at the beginning: the program doesn't even get as far as textOut.flushBuffer() on all the print attempts, it doesn't even get to the println method itself. It's probably, because it has to initialize some classes along the way, since it wasn't done before (like with a print at the beginning) and it can't, because the stack is overflowed. Thus, unlike the previous case with a print at the beginning, nothing is added to the buffer, so at the end we have only a single String printed (1024, 1 time).

I have no idea if that makes any sense, but it was certainly fun.

Shadov
  • 5,421
  • 2
  • 19
  • 38