finalize分析笔记

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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值