As far as I know this code should throw StackOverflowError, but it isn't. What could be the reason?
public class SimpleFile {
public static void main(String[] args) {
System.out.println("main");
try{
SimpleFile.main(args);
}
catch(Exception e){
System.out.println("Catch");
}
finally{
SimpleFile.main(args);
}
}
}
StackOverflowException is thrown for execution stack overflow errors, typically in case of a very deep or unbounded recursion. So make sure your code doesn't have an infinite loop or infinite recursion. StackOverflowException uses the HRESULT COR_E_STACKOVERFLOW, which has the value 0x800703E9.
A finally block always executes, regardless of whether an exception is thrown.
A StackOverflowException is thrown when the execution stack overflows because it contains too many nested method calls. using System; namespace temp { class Program { static void Main(string[] args) { Main(args); // Oops, this recursion won't stop. } } }
An Error is not an Exception
. So catching any exception won't catch the StackOverflowError.
So lets start by fixing the "obvious mistake" - (this code is inadvisable as stated later in this answer):
catch(Throwable e){
System.out.println("Catch");
}
If you make this change you will find the code still does not print. But it doesn't print for a very different reason...
Catching any ERROR
(including a StackOverflowError
) is highly discouraged. But here you are not only catching one, you're catching one as it happens at the top of the stack. Even with your code (without the above change) the error is effectively caught by the finally
block.
A StackOverflowError
occurs when the stack is full and you try to add more to it. So when you catch the error the stack is still full. You can not call any method (even to print to the console) because the stack is full. So a second StackOverflowError
is thrown in the catch
before it has successfully printed.
The result of this is that it:
finally
, because finally is always called.main
The key here is that eventually it will start printing something. But the call to print
uses a lot of stack space and your code will have to recurs and error through the above points for a very long time before it ever frees up enough stack space to print. According to Holger's comment With Oracle’s Java 8 to put the number of main
stack frames needed for a println
stack frame close to 50.
250 = 1,125,899,906,842,624
This is why YOU SHOULD NEVER CATCH ERRORS.
There are only a handful of excuses that allow you to break this rule, and you've discovered first hand what can go wrong if you do break it.
Actually you got java.lang.Stackoverflow
You can run this sample code:
public class SimpleFile {
public static void main(String[] args) {
System.out.println("main ");
try{
SimpleFile.main(args);
}finally{
try{
SimpleFile.main(args);
}catch(Error e2){
System.out.println("finally");
throw e2;
}
}
}
}
PS
More details: your program prints a lot of main
messages and after this you receives stack overflow error for first time and go to finally block. It means that you decrease stack size and now you can call something. But you call itself in finally block and get stack overflow again. Most surprising for me was unstable output:
main
main main finally
main
main main finallyfinallyfinally
main
main
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With