tags:

views:

2360

answers:

7

Is there any condition where finally might not run in java? Thanks.

+17  A: 

System.exit shuts down the Virtual Machine.

Terminates the currently running Java Virtual Machine. The argument serves as a status code; by convention, a nonzero status code indicates abnormal termination.

This method calls the exit method in class Runtime. This method never returns normally.

 try {
  System.out.println("hello");
  System.exit(0);
 }
 finally {
  System.out.println("bye");
 } // try-finally

"bye" does not print out in above code.

eed3si9n
+37  A: 

from the Sun Tutorials

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

I don't know of any other ways the finally block wouldn't execute...

hhafez
@dhiller - I'm pretty sure that "power down" is included in "If the JVM exits..." :-p
Jason Coco
@Jason Coco: Terminating (as upon loss of power) is not quite the same thing as exiting; the latter is a more or less organized process culminating in the former. ;p
+11  A: 

A non-programmatic way...pull the plug!

Al W
http://thedailywtf.com/Articles/My-Tales.aspx Finally!
Spoike
+8  A: 

Just to expand on what others have said, anything that does not cause something like the JVM exiting will incur the finally block. So the following method:

public static int Stupid() {
  try {
    return 0;
  }
  finally {
    return 1;
  }
}

will strangely both compile and return 1.

Daniel Nadasi
this really confused me for a good couple of hours a few weeks back.
nickf
It's considered a bad idea to return a value from a finally block. Either return only from the try block, or return from outside the try/finally block. Most IDEs will mark this with a warning.
Ran Biron
Also why it's a good idea to javac -Xlint (like cc -Wall -Wextra)
Jason Coco
+4  A: 

Related to System.exit, there are also certain types of catastrophic failure where a finally block may not execute. If the JVM runs out of memory entirely, it may just exit without catch or finally happening.

Specifically, I remember a project where we foolishly tried to use

catch (OutOfMemoryError oome) {
    // do stuff
}

This didn't work because the JVM had no memory left for executing the catch block.

Zarkonnen
When OutOfMemoryError is thrown there is usually lots of memory left (to stop GC thrashing). However, if you catch it repeatedly you obviously will get back to GC thrashing.
Tom Hawtin - tackline
+2  A: 
try { for (;;); } finally { System.err.println("?"); }

In that case the finally will not execute (unless the deprecated Thread.stop is called, or an equivalent, say, through a tools interface).

Tom Hawtin - tackline
This page claims that a ThreadDeath error is thrown, and that the stack unwinds normally when Thread.stop() is called. Is there a catch that I am missing? http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
spurserh
I don't think there's a catch. Perhaps there you are imagining a catch that isn't there. If we put in an explicit `throw`, then the `finally` block will execute as expected. `try { throw new ThreadDeath(); } finally { System.err.println("?"); }`
Tom Hawtin - tackline
+1  A: 

Sun tutorial has been wrongly quoted here in this thread

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

If you look into sun tutorial closely for finally block, it doesn't say "will not execute" but "may not execute" Here is the correct description

Note: 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. 

The apparent reason for this behavior is, call to system.exit() is processed in a runtime system thread which may take time to shutdown the jvm, meanwhile thread scheduler can ask finally to execute. So finally is designed to always execute, but if you are shutting down jvm, it may happen that jvm shuts down prior to finally getting being executed.

saurabh