对象的finalization机制

对象的finalization机制

1.Java提供了对象终止(finalization)机制来允许开发人员提供对象销毁之前的自定义处理逻辑。当垃圾收集器发现没有引用指向一个对象,即:垃圾回收此对象之前,总会先调用这个对象的finaliza()方法。finaliza()方法以内需在子类中被重写,用于在对象被回收之时进行资源的释放,通常在这个方法中进行一些资源释放和清理工作,比如关闭文件、套接字和数据库连接等。

2.永远不要主动调用某个对象的finalize()方法,应该交给回收机制调用,理由包括下面三点:

  • 在finalize()时可能导致对象复活。
  • 在finalize()方法执行时间没有保障,它完全由GC线程决定,极端情况下,若不发生GC,则finalize()方法将没有执行机会。
  • 一个糟糕的finalize()会严重影响GC的性能。

生存还是死亡?

如果从所有的根节点都无法访问到某一个对象,说明对象已经不再使用了,一般来说,此对象需要被回收,但事实上,也并非“非死不可”的,这时候他们暂时处于“缓刑”阶段。一个无法触及的对象有可能在某一个条件下“复活”自己,如果这样,那么对它的回收就是不合理的,为此,定义虚拟机中的对象可能的三种状态,如下:

  • 可触及的:从根节点开始,可以到达这个对象
  • 可复活的:对象的所有引用都被释放,但是对象有可能在finalize()中复活。
  • 不可触及的:对象的finalize()被调用,并且没有复活,那么就会进入不可触及状态,不可触及的对象不可能被复活,因为finalize()只会被调用一次。
    以上三种状态中,是由于finalize()方法的存在,进行区分的,只有在对象不可触及时才可以回收。

具体过程

判定一个对象objA是否可回收,至少要经历两次标记过程:
1.如果对象objA到GC Roots没有引用链,则进行第一次标记。
2.进行筛选,判断此对象是否有必要执行finalize()方法

  • 如果对象objA没有重写finalize()方法,或者finalize()方法已经被虚拟机调用过,则虚拟机视为“没有必要执行”,objA就判定为不可触及的
  • 如果对象objA重写了finalize()方法,并且还没有执行过,要么objA会被插入到F-Queue队列中,由一个虚拟机自动创建,低优先级的finalizer线程触发其finalize()方法执行。
  • finalize()方法是对象逃脱死亡的最后机会,稍后GC会对F-Queue队列中的对象进行第二次标记,如果objA在finalize()方法中与引用链中的任何一个对象建立了联系,那么在第二次标记时,objA会被移出“即将回收”集合,之后,对象如果再次出现没有引用链存在的情况下,这个情况下finalize()方法不会被再次调用,对象会被直接变成不可触及状态,也就是说,一个对象的finalize()方法只会被调用一次。

finalize方法代码演示

public class CanReliveObj {
    public static CanReliveObj obj;//类变量,属于 GC Root


    //此方法只能被调用一次
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("调用当前类重写的finalize()方法");
        obj = this;//当前待回收的对象在finalize()方法中与引用链上的一个对象obj建立了联系
    }


    public static void main(String[] args) {
        try {
            obj = new CanReliveObj();
            // 对象第一次成功拯救自己
            obj = null;
            System.gc();//调用垃圾回收器
            System.out.println("第1次 gc");
            // 因为Finalizer线程优先级很低,暂停2秒,以等待它
            Thread.sleep(2000);
            if (obj == null) {
                System.out.println("obj is dead");
            } else {
                System.out.println("obj is still alive");
            }
            System.out.println("第2次 gc");
            // 下面这段代码与上面的完全相同,但是这次自救却失败了
            obj = null;
            System.gc();
            // 因为Finalizer线程优先级很低,暂停2秒,以等待它
            Thread.sleep(2000);
            if (obj == null) {
                System.out.println("obj is dead");
            } else {
                System.out.println("obj is still alive");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值