Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

finally not throwing stack overflow exception

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);
        }
    }

}
like image 615
FIRST LAST Avatar asked Dec 03 '15 05:12

FIRST LAST


People also ask

How do I fix stack overflow exception?

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.

Does finally block execute if there is no exception?

A finally block always executes, regardless of whether an exception is thrown.

What causes StackOverflowException?

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. } } }


2 Answers

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:

  1. Catches the error
  2. trys to print the error
  3. causes another error because it can't print
  4. calls finally, because finally is always called.
  5. causes another error because it cant call main
  6. cascades the error back to the previous call which runs into the same error.

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.

like image 81
Philip Couling Avatar answered Oct 02 '22 14:10

Philip Couling


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 
like image 30
sibnick Avatar answered Oct 02 '22 15:10

sibnick