1. 程式人生 > >【Java】finally程式碼塊不被執行的情況總結

【Java】finally程式碼塊不被執行的情況總結

以前跟別人討論finally關鍵字,我總是簡單的說:“fianly程式碼塊中的程式碼一定會執行,一般用來清除IO資源等非記憶體資源(記憶體資源由GC機制回收)”。 今天翻書發現了幾種不會執行的情況,現在總結下。

1.finally的含義 finally的真正含義是指從try程式碼塊出來才一定會執行相應的finally程式碼塊。

public class Test { public static void main(String[] args) { foo(false); } public static void foo(boolean flag) { System.out.println(“enter foo()”); if(flag) { try { System.out.println(“enter try block”); } finally { System.out.println(“enter finally block”); } } else { System.out.println(“leave foo()”); }

}

} /****************** 控制檯列印如下 enter foo() leave foo() *******************/

上述程式碼,flag為false,沒有進入try程式碼塊,對應的finally自然也不會執行。

2.System.exit() System.exit()的作用是中止當前虛擬機器,虛擬機器都被中止了,finally程式碼塊自然不會執行。

public class Test { public static void main(String[] args) { foo(); } public static void foo() { System.out.println(“enter foo()”); try { System.out.println(“enter try block”); System.exit(); } finally { System.out.println(“enter finally block”); } } } /***************** 控制檯列印如下 enter foo() enter try block ******************/

上述程式碼,進入foo()方法後再進入try程式碼塊,但是在進入finally程式碼塊之前呼叫了System.exit()中止虛擬機器, finally程式碼塊不會被執行。

3.守護(daemon)執行緒被中止時 java執行緒分為兩類,守護執行緒和非守護執行緒。當所有的非守護執行緒中止時,不論存不存在守護執行緒,虛擬機器都會kill掉守護執行緒從而中止程式。 虛擬機器中,執行main方法的執行緒就是一個非守護執行緒,垃圾回收則是另一個守護執行緒,main執行完,程式就中止了,而不管垃圾回收執行緒是否中止。 所以,如果守護執行緒中存在finally程式碼塊,那麼當所有的非守護執行緒中止時,守護執行緒被kill掉,其finally程式碼塊是不會執行的。

public class Test { public static void main(String[] args) { Thread t = new Thread(new Task()); t.setDaemon(true); //置為守護執行緒 t.start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { throw new RuntimeException(“the “+Thread.currentThread().getName()+” has been interrupted”,e); } } } class Task implements Runnable { @Override public void run() { System.out.println(“enter run()”); try { System.out.println(“enter try block”); TimeUnit.SECONDS.sleep(5); //阻塞5s } catch(InterruptedException e) { System.out.println(“enter catch block”); throw new RuntimeException(“the “+Thread.currentThread().getName()+” has been interrupted”,e); } finally { System.out.println(“enter finally block”); } } } /******************* 控制檯列印如下 enter run() enter try block ********************/

上述程式碼,main()執行完,非守護執行緒也就結束了,雖然執行緒t處於阻塞狀態,但由於其是守護執行緒,所以程式仍會中止。 而且,即使其進入了try程式碼塊,finally程式碼塊也不會被執行。

總結 finally程式碼塊並非一定執行,在不進入try程式碼塊或者程式被中止時就不會執行。