以前只知道不管 try 语句块正常结束还是异常结束,finally 语句块是保证要执行的。但是以下情况finally是不执行的!
1)只有与 finally 相对应的 try 语句块得到执行的情况下,finally 语句块才会执行;
2)在 try 语句块中执行了 System.exit (0) 语句,终止了 Java 虚拟机的运行,finally是不执行的!
3)当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的 finally 语句块可能不会执行。
4)突然死机或者断电!
如果 try 语句块正常结束,那么在 try 语句块中的语句都执行完之后,再执行 finally 语句块。
如果 try 中有控制转移语句(return、break、continue)呢? finally 语句块是在控制转移语句之前执行!
如果 try 语句块异常结束,如果 catch 语句块中包含控制转移语句呢? finally 语句块还是在这些控制转移语句之前执行!
控制转移语句除了 return 外,还有 break 和 continue。另外,throw 语句也属于控制转移语句。其中 return 和 throw 把程序控制权转交给它们的调用者(invoker),而 break 和 continue 的控制权是在当前方法内转移。
Java 虚拟机是如何编译 finally 语句块?实际上,Java 虚拟机会把 finally 语句块作为 subroutine,直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。
但是,还有另外一个不可忽视的因素,那就是在执行 subroutine(也就是 finally 语句块)之前,try 或者 catch 语句块会保留其控制转移语句的返回值到本地变量表(Local Variable Table)中。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者(invoker)。上面提到过 return、throw 和 break、continue 的区别,对于这条规则(保留返回值),只适用于 return 和 throw 语句,不适用于 break 和 continue 语句,因为它们根本就没有返回值。