3

Consider below code,

public class Test {

    public void abc() {
        try {
            throw new OutOfMemoryError();
        } finally {
            System.out.println("finally");
        }
    }

    public static void main(String[] args) {
        new Test().abc();
    }

}

Output :

Exception in thread "main" finally
java.lang.OutOfMemoryError
    at Test.abc(Test.java:5)
    at Test.main(Test.java:12)

So, finally block is getting executed in the case, however above output is not fixed each time.

  1. So the question is, Here we are throwing OutOfMemoryError and finally block is getting executed. Is this true for every case ?

  2. If yes then finally block will be executed when OutOfMemoryError will be thrown in reality, means memory area expansion will be performed while execution and enough memory not available ?

Not a bug
  • 4,286
  • 2
  • 40
  • 80
  • 6
    That's right. And another `OutOfMemoryError` may be thrown inside the `finally` block which will supersede the other one. – Sotirios Delimanolis Apr 09 '14 at 16:50
  • In that case eclipse warning is : "finally block does not complete normally". – Not a bug Apr 09 '14 at 16:54
  • @KishanSarsechaGajjar - that error appears s because you're explicitly throwing the exception. In the real world it just happens. – kdgregory Apr 09 '14 at 17:15
  • And to add to what @SotiriosDelimanolis said - if a second OOM -- or any other exception -- happens in the middle of your `finally`, it means that your `finally` won't be completely executed. – kdgregory Apr 09 '14 at 17:16
  • 1
    The output is not 'fixed' because the message `finally` gets written to standard output but the stacktrace gets written to standard error. Try `System.err.println("finally")` instead. – Luke Woodward Apr 09 '14 at 17:27

2 Answers2

2

that's right like said Sotirios Delimanolis

and more surprisingly even if you put a return in your try block the finally will be executed

From the doc :

"finaly block allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated"

check this for more information http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html

Not a bug
  • 4,286
  • 2
  • 40
  • 80
user43968
  • 2,049
  • 20
  • 37
  • There is a [SO question](http://stackoverflow.com/q/65035/1686291) on `return`. Please explain in context of `OutOfMemoryError`. – Not a bug Apr 09 '14 at 17:01
  • Looks pretty explanatory. In case of OOM, the finally block __will be executed__. – Giovanni Botta Apr 09 '14 at 18:12
  • @GiovanniBotta `"more surprisingly even if you put a return..."` It is not surprising at all...I know that already. I want to know behavior in context of `OutOfMemoryError` not in context of `return` statement. – Not a bug Sep 25 '14 at 11:40
  • @KisHanSarsecHaGajjar I think OOM is no different from any other error/exception. The only way the finally block will __not__ execute is if you call [`System.exit()` or the whole JVM has already crashed](http://stackoverflow.com/questions/65035/does-finally-always-execute-in-java), which in all fairness could happen when OOM happens on some platforms. However, I have seen JVMs resiliently surviving OOM, although they would behave unpredictably. – Giovanni Botta Sep 25 '14 at 15:31
  • @GiovanniBotta What about `for(;;){}` ? (PS : I found this on same question you provided) – Not a bug Sep 25 '14 at 18:35
  • @KisHanSarsecHaGajjar as somebody summarized on that thread, the finally will always be executed __after leaving the try block__. If you prevent your code from leaving the try block (as with an infinite loop) then there is no way __anything else__ will ever be executed. Unless of course an exception is thrown from within the loop, in which case it won't be infinite. The point here is that OOME is not "special" in any way. – Giovanni Botta Sep 25 '14 at 18:59
  • @KisHanSarsecHaGajjar why don't you write a small program to test the behavior yourself? Just start the JVM with a small amount of memory and allocate a lot of objects and see what happens. There's no point in continuing this conversation until you try it by yourself. And if you find any odd behavior please post it. It will be everybody's pleasure to figure out what is going on. – Giovanni Botta Sep 25 '14 at 19:01
2

Things will get interesting if you try to do something in the finally block requiring additional memory:

public class Finally {

    public void abc() {
        try {
            throw new OutOfMemoryError();
        } finally {
            byte[] b = new byte[1024*1024*1024];
            System.out.println("finally");
        }
    }

    public static void main(String[] args) {
        new Finally().abc();
    }
}

Now when you execute the code (java -Xmx20m Finally for example), you can easily end up in a situation where your available heap has been exhausted to the extent where the finally block cannot fully complete, thus its execution cannot be guaranteed. So I would not recommend to rely on finally blocks in case of OutOfMemoryErrors.

Not a bug
  • 4,286
  • 2
  • 40
  • 80
Ivo
  • 444
  • 3
  • 7