25

I'm a Java rookie and I was wondering, if I have the following typical Java code

public class MyApp {
  public static void main(String[] args) {
    try {
      // do stuff
    } catch {
      // handle errors
    } finally {
      // clean up connections etc.
    }
  }
}

does the JVM guarantee that the finally block will always be run? To understand where I'm coming from, I'm used to C/C++ programs that might just crash if you dereference a NULL pointer and you can't have any code to be run after that.

But as I understand Java and the whole GC / managed memory business in general, there's no such thing as a null pointer dereferencing, everything is a catchable expection, so there's not really a way for my program to crash that could make it skip the finally, or is there? For example, in Python, I usually do

try:
  # do stuff
except AnExceptionIKnewMightHappen:
  # react in an appropriate way
except:
  # log that weird error I had not known could happen

and I have never had any app die without passing through my code.

Of course, if the OS for some reason kills the process (or if something kills the whole system, like pulling the plug) there's not much Java can do. Also, from PHP I know non-catchable errors that you can't protect against, even though the interpreter was still there after it happened (at least it is able to output a proper message).

Edit: Just for clarity (it wasn't really misunderstood by anyone), let me add that I was looking for things inside my code that could lead to the finally being bypassed. So pointing to System.exit was a helpful reminder, even though I can't see why I would want to do something like that.

The JVM exiting is a rather obvious way and I'd count that as an external cause. The note pointing out that you also have to remember the possibilty of threads exiting while the JVM and the app keep running was very helpful, because even though it also seems obvious to me now, I hadn't thought of it.

Hanno Fietz
  • 30,799
  • 47
  • 148
  • 234

10 Answers10

49

Basically yes, except for the note listed here (emphasis mine):

If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.

  • 20
    Note that pulling the power cord is usually a good way to prevent "finally" from running, too... – Bill Michell Feb 05 '09 at 14:43
  • 3
    LOL - and if it's a laptop, the batteries in the laptop die at the same moment :D –  Feb 05 '09 at 15:59
  • 6
    Dropping the laptop out of the top story of a sky scraper also prevents both finally blocks *and* shutdown hooks!! – Lawrence Dol Feb 06 '09 at 07:02
  • Nope. The link you quoted that the finally block **may** not execute. It doesn't say that it **will not** execute. Wrong quoting. – luis.espinal Mar 15 '11 at 12:05
  • @Software Monkey I would like to say that this is wrong. Since while falling there is time to execute both blocks (except in rare cases when you are doing something really time intensive). – Igor Čordaš Aug 15 '13 at 10:15
  • @PSIXO: Only if you initiate the shutdown before dropping it. – Lawrence Dol Aug 15 '13 at 18:00
  • I'm pretty sure if you pull the power cord the finally block gets pushed up to teh Cloud and executed there. Water is wet, night follows day, and finally blocks always run. – Outback Jul 22 '14 at 18:29
13

It is not guaranteed:

public class Main {
    public static void main(String args[]) {
        try {
            System.out.println("try");
            System.exit(0);
        } catch (Exception e) {
            System.out.println("exception");
        } finally {
            System.out.println("finally");
        }
    }
}

Run that.

cletus
  • 616,129
  • 168
  • 910
  • 942
  • Not quite sure how that's relevant to "so there's not really a way for my program to crash that could make it skip the finally, or is there?" Obviously if you quit the JVM, powercycle the box or shoot the monitor then finally won't run. Surprised at the up-votes, but then maybe I'm just jealous :) – Rob Grant Feb 05 '09 at 14:24
  • It's simple proof by counterexample. Obviously it's not guaranteed. That may or may not be important to you. And if it happens on a "clean" exit, I guarantee you it's no better on an actual crash. – cletus Feb 05 '09 at 14:33
  • I think that it's safe to say System.exit() is a special case – matt b Feb 05 '09 at 14:35
  • Special or not, it's a case and a valid one at that. There's a HUGE difference between "finally is guaranteed" and "finally is normally guaranteed". – cletus Feb 05 '09 at 14:40
  • 2
    To add my 2ct, I thought it was a helpful reminder that you actually can bypass it with ordinary code (i. e. without errors), even though I can't think of a reason right now why I should want to exit the program that way. I'm new to Java and it helped. – Hanno Fietz Feb 05 '09 at 14:47
10

In a word, yes.

Code in the finally block in Java always executes unless:

  • The JVM exits during the try or catch block
  • The thread running the code is interrupted or killed during the try or catch block

(from: http://java.sun.com/docs/books/tutorial/essential/exceptions/finally.html)

So, unless you explicitly call System.exit(int), or kill the process or thread externally, you can rely on it.

Martin McNulty
  • 2,601
  • 3
  • 22
  • 26
4

Absolutely, that finally block will run, every time. Except in the case of a JVM crash or the exit() function being called. I have had code where the Java application made calls out to JNI native code which segfaulted. The resulting crash killed the JVM, and prevented the finally from running.

Arcane
  • 1,230
  • 1
  • 8
  • 15
2

Chris Cameron is correct. But normally a finally-block gets executed. Null pointer dereferece does exist in Java:

try {
    List<Object> x = null;
    x.get(1); //throws the unchecked NullPointerException
} finally {
    //will be executed
}

The finally-Block gets executed.

Johannes Weiss
  • 52,533
  • 16
  • 102
  • 136
1

Yes, the JVM always executes it. Gaurranteed.

Of course ... if the JVM itself dies (eg: System.exit()), then it's not in a position to gaurrantee anything. But the JVM dying is not a within-java issue.

paulmurray
  • 3,355
  • 1
  • 22
  • 17
  • 2
    This is not correct. **Thread.stop()** can prevent **finally** blocks while the JVM still remains running. – Alain O'Dea Jun 09 '14 at 17:21
  • 2
    @AlainO'Dea no, `Thread.stop()` does not prevent `finally` blocks from executing. – Holger Jul 01 '19 at 17:22
  • @Holger the situation is more nuanced than I originally thought. Thread.stop() forces the thread to throw ThreadDeath from wherever it is. The implications are better described here: https://stackoverflow.com/a/29373113/154527. – Alain O'Dea Jul 02 '19 at 19:18
  • 2
    @AlainO'Dea that linked answer describes the situation very well. `Thread.stop()` does not prevent the execution of `finally` when the thread was inside the `try` block, but it may prevent its completion when the thread was already inside the `finally` block. Note that these are the same restrictions as for ordinary code flow constructs. If a thread never reaches a `try` block, the `finally` block won’t be executed, further, `break` and `continue` targeting a loop outside the `try` construct or `return`,`throw` or any provoked exception within the `finally` block may prevent its completion. – Holger Jul 03 '19 at 09:20
  • @Holger great clarification. Thank you. I think it was the stop while processing finally that provoked my original comment. I wish I had provided more detail on my rationale for that response and better caveats. – Alain O'Dea Jul 04 '19 at 10:10
0

the only exceptions finally block is not executed are, either JVM crashes, or system.exit().

Jackie
  • 25,199
  • 6
  • 33
  • 24
0

It seems pretty obvious that nothing more will run after JVM quit, or will run code in that killed thread. Obvious. So, when the JVM is running, every code that will run, will run, and after a JVM quit or inside a dead thread , nothing will run, even any kind of code. So, there is no way to prevent, but if there is a need to the finally clause, put it.

backslash
  • 1
  • 1
0

Erm, yep :) Whether your code enters a catch or not, the finally will run. It's a good place to put code that cleans up after the try.

Obviously it won't run if you break the jvm :)

Rob Grant
  • 7,239
  • 4
  • 41
  • 61
0

Yes, the finally block will always be run, unless there is a crash of the JVM (very rare, but that can happen).

Guillaume
  • 18,494
  • 8
  • 53
  • 74