Does a finally block always run?

2019-01-02 17:27发布

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

标签: java finally
12条回答
其实,你不懂
2楼-- · 2019-01-02 17:58

In following cases, finally block will not be executed :-

  • When System.exit(0) is invoked from try block.
  • When JVM runs out of memory
  • When your java process is killed forcefully from task mgr or console
  • Deadlock condition in your try block
  • When your machine shuts down due power failure

There may also be other fringe cases, where finally block will not be executed.

查看更多
君临天下
3楼-- · 2019-01-02 18:00

There are two ways to stop finally block code execution:
1. Use System.exit();
2. If somehow execution control don't reach to try block.
See:

public class Main
{
  public static void main (String[]args)
  {
    if(true){
        System.out.println("will exceute");
    }else{
        try{
            System.out.println("result = "+5/0);
        }catch(ArithmeticException e){
          System.out.println("will not exceute");
        }finally{
          System.out.println("will not exceute");  
        }
    }
  }
}
查看更多
墨雨无痕
4楼-- · 2019-01-02 18:04

I've come across a very specific case of the finally block not executing related specifically to the play framework.

I was surprised to find that the finally block in this controller action code only got called after an Exception, but never when the call actually succeeded.

try {
    InputStream is = getInputStreamMethod();
    renderBinary(is, "out.zip");
catch (Exception e) {
    e.printStackTrace();
} finally {
    cleanUp();
}

Perhaps the thread is terminated or something when renderBinary() is called. I would suspect the same thing happens for other render() calls, but I didn't verify it.

I solved the problem by moving the renderBinary() to after the try/catch. Further investigation revealed that play provides an @Finally annotation to create a method that gets executed after a controller action executes. The caveat here is that this will get called after the execution of ANY action in the controller, so it may not always be a good choice.

查看更多
时光乱了年华
5楼-- · 2019-01-02 18:05

from the Sun Tutorials

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.

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

查看更多
公子世无双
6楼-- · 2019-01-02 18:07

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.

查看更多
素衣白纱
7楼-- · 2019-01-02 18:08

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

查看更多
登录 后发表回答