Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stack overflow error handling in finally block

I have a program in java, which runs infinite times.

Program code:

void asd()
{
    try
    {
        //inside try block
        System.out.println("Inside try !!!");
        asd();
    }
    finally
    {
        //inside finally
        System.out.println("Inside finally !!!");
        asd();
    }
}

OUTPUT : this program runs infinitely, by constantly printing both the sysouts.

My question : At some point, it starts throwing StackOverflowErrors from the try block and so it reaches the finally block, where we are again calling this function recursively. But how is the recursive function in the finally block being executed as we already facing a StackOverflowError?

How does the JVM handle this situation? Will the same behavior occur if we get OutOfMemoryErrors too?

like image 709
ideano1 Avatar asked Jul 24 '13 13:07

ideano1


People also ask

How do you handle errors in finally block?

If the exception is not handled at the higher level, the application crashes. The "finally" block execution stops at the point where the exception is thrown. Irrespective of whether there is an exception or not "finally" block is guaranteed to execute. Then the original exception that occurred in the try block is lost.

Does finally run on error?

The Rule. The finally block on a try / catch / finally will always run — even if you bail early with an exception or a return .

Will finally be executed without exception?

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

Does finally always execute in try catch?

The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs.


1 Answers

The problem is that your example program is pathological. It won't work, and it can't work.

But how the recursive function in the finally block gets executed as we already facing StackOverflowError.?

There is a rather complicated sequence of calls going on. Lets assume that the stack can hold 3 frames. A "hand execution" gives us a sequence of calls / call-stack snapshots as follows:

asd()
asd() > try
asd() > try > asd() 
asd() > try > asd() > try 
asd() > try > asd() > try > asd() // Stack Overflow!
asd() > try > asd() > finally
asd() > try > asd() > finally > asd() // Stack Overflow!
asd() > finally
asd() > finally > asd()
asd() > finally > asd() > try
asd() > finally > asd() > try > asd() // Stack Overflow!
asd() > finally > asd() > finally
asd() > finally > asd() > finally > asd() // Stack Overflow!

END

As you can see with a stack of depth 3, we made 7 calls, 4 of which failed with a stack overflow. If you do the hand execution for a stack of depth 4, you will get 15 calls, 5 => 31. The pattern is N => 2**N - 1 calls.

In your case, the default stack is going to be able to accommodate hundreds, or even thousands of recursive calls.

Say N = 100. 2**100 is a very large number of calls. It is not infinite, but you will probably be dead before the program terminates.

How does the JVM handle this situation?

As above. The JVM is not doing anything special. The "effectively infinite loop" behaviour is entirely down to the way that your program is written.

Will the same behaviour occur if we get OutOfMemoryErrors too?

Erm ... it depends on your program. But I'm sure you could concoct an example program that exhibited a similar pattern of behaviour.

like image 193
Stephen C Avatar answered Oct 23 '22 17:10

Stephen C