finalize()是Object類里的protected類型的方法,子類(所有類都是Object的子類)可以通過覆蓋這個方法來實現回收前的資源清理工作。和這個方法相關的流程如下所述。
1 Java虛擬機一旦通過剛才提到的“根搜索算法”判斷出某對象處於可回收狀態時,會判斷該對象是否重寫了Object類的finalize方法,如果沒,則直接回收。
2 如重寫過finalize方法,而且未執行過該方法,則把該對象其放入F-Queue隊列,另個線程會定時遍歷F-Queue隊列,並執行該隊列中各對象的finalize方法。
3 finalize方法執行完畢后,GC會再次判斷該對象是否可被回收,如果可以,則進行回收,如果此時該對象上有強引用,則該對象“復活”,即處於“不可回收狀態”。
通過下面的FinalizeDemo.java,我們來演示下通過finalize方法復活對象的做法。
1 public class FinalizeDemo { 2 static FinalizeDemo obj = null; 3 //重寫Object里的finalize方法 4 protected void finalize() throws Throwable { 5 System.out.println("In finalize()"); 6 obj = this; //給obj加個強引用 7 } 8 public static void main(String[] args) throws InterruptedException { 9 obj = new FinalizeDemo(); 10 obj = null; //去掉強引用 11 System.gc(); //垃圾回收 12 //sleep 1秒,以便垃圾回收線程清理obj對象 13 Thread.sleep(1000); 14 if (null != obj) { //在finalize方法復活 15 System.out.println("Still alive."); 16 } else { 17 System.out.println("Not alive."); 18 } 19 } 20 }
在main函數里的第9行里,我們給第2行定義的obj對象分配了一塊內存空間,並在第10行去掉obj所指空間的強引用,在第11行,通過System.gc方法啟動了垃圾回收機制。
這時,由於obj所指向的對象上沒有強引用,所以這塊對象可以被回收,在回收前,是會執行其中的finalize方法。
在第4行重寫的finalize方法里,我們給obj對象加了一個強引用,這樣的話,在finalize方法被執行后,obj對象就不符合被回收的條件了,所以在第14行的if…else判斷里,走第15行的流程,輸出“still alive.”這句話。
不過,由於垃圾回收和遍歷F-Queue隊列不是同一個線程,所以一旦重寫了這個方法,就有可能導致對象被延遲回收,如果這個方法再被放入錯誤的代碼,就極有可能導致該對象無法回收。
所以回到本文開始的兩個問題。
第一,finalize方法干嘛的?
在其中可以編寫對象被回收時的動作,具體的流程大家可以按本文給出的意思說一遍。
第二,你有沒有重寫過這個方法?
由於重寫finalize不當,會導致該對象無法回收,所以在項目里,我們一般不重寫該方法,而會采用Object類自帶的空的finalize方法。
轉:https://www.cnblogs.com/JavaArchitect/p/14290452.html