如何判断对象已“死”

Java堆中存放着几乎所有的对象实例,垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象哪些还存活,哪些已经“死去”。判断对象是否已“死”有如下几种算法:

引用计数法

算法思想:给每一个对象附加一个计数器,每当有一个地方引用此对象时,计数器+1;每当有一个引用失效是,计数器-1;在任意时刻,只要计数器值为0的对象就是不能再被引用的,即对象已死。

引用计数法实现简单,判断效率也较高,但是无法解决循环引用问题。
JVM并未采用此代码。

public class Test {
  public Object instance = null;
  public static void testGC() {
  Test test1 = new Test();
  Test test2 = new Test();
  test1.instance = test2;
  test2.instance = test1;
  test1 = null;
  test2 = null;
 // 强制jvm进行垃圾回收
 System.gc();
 }

如上代码,虚拟机并没有因为这两个对象相互引用就不回收他们,所以JVM并不使用引用计数法来判断对象是否存活。

可达性分析算法

Java采用可达性分析算法来判断对象是否存活。

算法思想:通过一系列“GC Roots”的对象作为起点,从这些节点开始向下搜索对象,搜索走过的路径称为“引用链”,当一个对象到任意一个GC Roots对象没有任何的引用链相连是(从GC Roots到对象不可达),证明对象已死。

在这里插入图片描述
对象object 5 - object 7 之间虽然彼此还有关联,但是他们到GC Roots是不可达的,因此他们会被判定为可回收对象。

Java中能作为GC Roots的对象包含一下四种:
1.虚拟机栈中引用的对象
2.类静态变量引用的对象
3.常量引用的对象
4.本地方法栈中引用的对象

对象的自我拯救(finalize)

在可达性分析方法中不可达的对象,并非“非死不可”,所有不可达对象处于“缓刑”阶段,要宣告一个对象的彻底死亡,需要经历两次标记过程:

若对象在进行可达性分析之后,发现到GC Roots不可达,此对象会进行第一次标记并且进行一次筛选过程。筛选的条件是此对象是否有必要执行finalize()。当对象没有覆盖finalize()方法或者finalize()已经被JVM调用过,JVM会将此对象彻底宣告死亡。
筛选成功(此对象覆写了finalize()方法并且未被执行),会将此对象放入一个叫F-Queue的队列中,如果对象在finalize()成功自救(此对象与GC Roots建立练习),则对象会在第二次会被移除回收集合,成功存活;若对象在finalize()中仍然与GC Roots不可达,宣告死亡。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值