finally 語句塊是在 try 或者 catch 中的 return 語句以前執行的。更加通常的說法是,finally 語句塊應該是在控制轉移語句以前執行,控制轉移語句除了 return 外,還有 break 和 continue。另外,throw 語句也屬於控制轉移語句。雖然 return、throw、break 和 continue 都是控制轉移語句,可是它們之間是有區別的。其中 return 和 throw 把程序控制權轉交給它們的調用者(invoker),而 break 和 continue 的控制權是在當前方法內轉移。翻譯
關於 Java 虛擬機是如何編譯 finally 語句塊的問題,有興趣的讀者能夠參考《 The JavaTM Virtual Machine Specification, Second Edition 》中 7.13 節 Compiling finally。那裏詳細介紹了 Java 虛擬機是如何編譯 finally 語句塊。實際上,Java 虛擬機會把 finally 語句塊做爲 subroutine(對於這個 subroutine 不知該如何翻譯爲好,乾脆就不翻譯了,省得產生歧義和誤解。)直接插入到 try 語句塊或者 catch 語句塊的控制轉移語句以前。可是,還有另一個不可忽視的因素,那就是在執行 subroutine(也就是 finally 語句塊)以前,try 或者 catch 語句塊會保留其返回值到本地變量表(Local Variable Table)中。待 subroutine 執行完畢以後,再恢復保留的返回值到操做數棧中,而後經過 return 或者 throw 語句將其返回給該方法的調用者(invoker)。請注意,前文中咱們曾經提到過 return、throw 和 break、continue 的區別,對於這條規則(保留返回值),只適用於 return 和 throw 語句,不適用於 break 和 continue 語句,由於它們根本就沒有返回值。對象
throw的狀況同理,例如,當某段指令出現異常時,將會產生一個 exception 對象,而且把它壓入當前操做數棧的棧頂。接下來是 astore_X 這條指令,它負責把 exception 對象保存到本地變量表中 X 的位置,而後執行 finally 語句塊,待 finally 語句塊執行完畢後,再由 aload_X 這條指令把預先存儲的 exception 對象恢復到操做數棧中,最後由 athrow 指令將其返回給該方法的調用者(main)。ci