关于GC过程中对象的两次标记

1.前言
前几天面试过程中被问到了垃圾收集,面试官问了我垃圾收集是怎么实现的,然后我就把运行时数据区里的堆里的新生代和老年代介绍了一遍,又指出新生代里的eden和survivor,再说了说复制算法,标记清除和标记整理算法。最后面试官又问我,那你说说怎么判断一个对象可以被回收把,我说了引用为0以及标记对象两次(也就是引用计数器可达性算法)。重点来了,面试官又问我你说的两次标记,是什么意思呢?我哑口了。。我只记得有两次标记,但是并不知道是怎么实现的,于是面试完后记录下问题,开始准备这篇文章。
在弄明白标记对象两次前, 首先认识一下finalize()。

2.finalize() 方法
finalize位于object内,当垃圾回收器将要回收对象之前会检查当前对象的finalize()是否被重写以及是否被执行(因为finalize()只能执行一次),如果是被重写以及没被调用过就调用这个方法。但GC不保证方法会被执行完。也就是说两次标记是为了看死期将至的对象还有没有遗言要说。

3.两次标记
第一次标记:通过GC roots遍历,找到不在关系网内的对象。并检查是否需要执行finalize()方法。(也就是说如果没重写finalize()则只需要标记一次,然后就可以GC)

在第一次标记中有遗言(finalize()需要被执行)的对象,会被丢到一个优先级较低的队列中执行,但不保证执行完

第二次标记:对队列中的对象再遍历一次,还是不在关系网内的对象就被打上标记,待会送去人道毁灭。

看到这里恐怕你也会和我有一样的疑问:
第一,既然finalize()是遗言,为什么不让他说完再让他死呢?
第二,假如看到文章后,你和我一样也打开了eclipse调用起了object的finalize()方法,你会发现finalize()在JDK9已经被打上强烈不赞同(deprecation)的标记了。那么是不是从JDK9开始就变成GC只要标记一次了呢?

第一个问题是finalize运行可能会导致死锁或是死循环。
第二个问题说实话不太懂…那就上代码把

public static void main(String[] args){
		QueueTest qt = new QueueTest();
		qt=null;
		System.gc();
}
@Override
	protected void finalize()throws Exception {
		System.out.println("救救我吧");
	}

输出: 救救我吧

那就说明finalize()在GC机制中还在用。但是我还是不懂,既然不推荐用,为什么还要用呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值