GC执行finalize的过程以及对象的一次自我拯救

参考资料:深入理解java虚拟机

 1 /**
 2  * 此代码演示了两点:
 3  * 1.对象可以在被GC时自我拯救
 4  * 2.这种自救的机会只有一次,因为一个对象的finalize()方法只会被系统自动调一次  
 5  */
 6 public class GC {  
 7   
 8     public static GC SAVE_HOOK = null;  
 9   
10     public static void main(String[] args) throws InterruptedException {  
11         SAVE_HOOK = new GC();
12         //对象第一次拯救自己,并且成功了
13         SAVE_HOOK = null;  
14         System.gc();
15         //因为GC执行finalize方法的优先级很低,所以暂停一会  
16         Thread.sleep(500);  
17         if (null != SAVE_HOOK) {
18             //这句话输出了 
19             System.out.println("Yes , I am still alive");  
20         } else {  
21             System.out.println("No , I am dead");  
22         }
23         //第二次拯救自己,失败了  
24         SAVE_HOOK = null;  
25         System.gc();  
26         Thread.sleep(500);  
27         if (null != SAVE_HOOK) {  
28             System.out.println("Yes , I am still alive");  
29         } else {
30             //因为一个对象的finalize方法只会被调用一次
31             System.out.println("No , I am dead");  
32         }  
33     }  
34   
35     @Override  
36     protected void finalize() throws Throwable {  
37         super.finalize();  
38         System.out.println("execute method finalize()");  
39         SAVE_HOOK = this;  
40     }  
41 }      

当jvm利用可达性分析算法检测到一个对象不可达时,jvm并不会立即回收该对象,要经过两次标记。

第一次标记,如果该对象没有覆盖finalize方法,或者该对象的finalize方法已经执行过,则立即将其回收,不经过二次标记;

第二次标记,jvm会把该对象放到一个F-Queue的队列中,等待执行finalize方法(这里的执行是指jvm会触发这个方法,但并不会保证会等待它运行结束),如果该对象在finalize方法中重新与引用链上的任何一个对象建立关联,那么该对象重新复活;如果该对象在finalize方法中什么也不做,那么该对象仍然会被回收

 

posted @ 2019-05-13 10:43  caotao0918  阅读(254)  评论(0编辑  收藏  举报