finalize分析笔记

    技术2026-04-08  1

    package com.test;

    public class Son {

        static boolean isgcrun=false;     static boolean flag=false;     static int created=0;     static int finalized=0;     int i;

        public Son(){         i=++created;         if(i==100){             System.out.println("i have 100 sons");         }     }

        protected void finalize() throws Throwable {         if(!isgcrun){             isgcrun = true;             System.out.println("gc kill sons...start!!!,"+ i + " sons killed ");         }         if(i==100){             System.out.println("-------set flag!!!---don't kill son!!!----");             flag = true;         }         finalized ++ ;         if(finalized >= created){             System.out.println("all killed!!!");         }     } }

    package com.test;

    public class Father {

        public static void main(String[] args) {         while(!Son.flag){               new Son();               new String("站岗中。。。。");           }

             System.out.println( "After all son have been created:/n"+                   "total created ="+Son.created+                   ",total finalized ="+Son.finalized);          System.out.println("gc():");          System.gc();          System.out.println("runFinalization():");          System.runFinalization();          System.out.println("bye");     } } 运行结果: i have 100 sons gc kill sons...start!!!,4544 sons killed -------set flag!!!---don't kill son!!!---- After all son have been created: total created =47649,total finalized =30257 gc(): runFinalization(): all killed!!! bye

    分析: 在一个循环当中创建对象,并且只是创建,而不引用,也就是说这个对象会自动的被系统当作垃圾处理掉。 但请注意,finalize()方法并不是立刻就会执行的,执行的时间完全由系统来决定。 所以很有可能的情况是已经创建了20000个对象,才开始其中的某一个对象的清除工作(这可能和时间或者系统内容的占用有关)。 为什么会被自动被系统当作垃圾回收?系统什么时候开始回收? 我们从jvm的gc顺序中可以分析得到答案 A. JVM会试图为相关Java对象在Eden中初始化一块内存区域(所有新对象不断的创建,并放在Eden中,使得Eden不断膨胀) B. 当Eden空间足够时,内存申请结束。否则到下一步(对象太多,内存资源开始不足) C. JVM试图释放在Eden中所有不活跃的对象(没有任何引用的对象为不活跃对象,判断原则;系统将会决定在这个时候回收掉这个对象)

    引:不活跃对象判断原则(http://hi.baidu.com/jieriw/blog/item/6f690f32f793e6cda3cc2bd5.html) 应用阶段:即该对象至少有一个引用在维护他. 不可视阶段:即超出该变量的作用域。这里有一个很好的做法,因为JVM在GC的时候并不是马上进行回收,而是要判断对象是否被其他引用在维护.所以,这个时候如果我们在使用完一个对象以后对其obj=null或者obj.doSomething()操作,将其标记为空,可以帮助JVM及时发现这个垃圾对象. 不可到达阶段:就是在JVM中找不到对该对象的直接或者间接的引用。 可收集阶段,终结阶段,释放阶段:此为回收器发现该对象不可到达,finalize方法已经被执行,或者对象空间已被重用的时候。

    我们从这可以发现垃圾回收过程往往都会迟一点才开始,如果有足够的时间gc还是能把这些没用的对象都回收了(让线程wait一会就能看到了),这也是为啥我们都选择在finally中进行文件流之类的关闭操作,因为finalize可靠了,母猪都会爬树了(当然现在母猪也有可能会爬树了);

    另外对于finalize的不可靠,Java 1.1 通过提供一个Runtime.runFinalizersOnExit()方法部分地解决了这个问题(现在使用Runtime.exit())。Runtime.exit() 方法并不立即试图启动垃圾回收器。而是当应用程序退出时,它调用每个对象的finalize()方法。

    正如你可能猜测的那样,通过调用Runtime.exit()方法强制垃圾回收器清除所有独立对象的内存,当清除代码执行时也可能引起明显的延迟。

    文章出处:http://www.dxmath.com/

    最新回复(0)