Java GC的过程

一.如何判断对象“已死”,目前主要有两种主流的算法
1.引用计数算法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器就+1,当引用失效时,计数器就-1,任何时候,计数器为0的对象就是不可能再被使用的。但是这种算法很难解决对象间互相循环引用的问题:

A a = new A();
A b = new A();
b.instance = a;
a.instance = b;
a = null;
b = null;


这个时候a和b的引用计数器都还没有变成0,因此他们不能被回收。

2.根搜索算法
主流的商业语言中(Java、C#)都是使用根搜索算法(GC Roots Tracing)来判断对象是否存活的。这个算法的基本思路就是通过一系列名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。


二.JVM如何判断对象能否回收

 

上图将对象的回收条件详细的说明了。

根搜索算法找到的这些不可达对象并非是“非死不可”的,这时候它们暂时处于缓刑阶段,要真正宣告一个对象死亡,至少要经过两次标记过程:

            A、 根搜索算法找到了一个不可达对象,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize 方法。当对象没有覆盖 finalize 方法,或者 finalize 方法已经被执行过,虚拟机将这两种情况都视为没有必要执行 finalize 方法 。

            B、 如果这个对象有必要执行 finalize 方法,那么该对象将会被加入到一个名为 F-Queue 的队列中,并在稍后由一条虚拟机自动建立的、低优先级的线程去执行。这里所谓的执行是指虚拟机会触发这个方法,但并不承诺会等待它执行结束这样做的原因是,如果一个对象的 finalize 方法执行缓慢或者存在死循环,将可能导致队列中的其他对象永远处于等待状态,甚至导致整个内存回收系统的崩溃Finalize 方法是对象逃脱死亡命运的最后一次机会。稍后 GC 将对 F-Queue 中的对象进行第二次小规模的标记, 如果对象在 finalize 中成功拯救自己(比如 aaa this 这种方式,重新与引用链上的任何一个对象建立关联即可),那么第二次标记时它将会被移除出“即将回收的集合”。如果它没有成功逃脱,那么它就真的离死不远了。

        任何一个对象的 finalize 方法都只会被系统调用一次,如果对象面临第二次回收,它的 finalize 将不会再次被执行。不过finalize方法运行代价高昂,不确定性大,无法保证各个对象的调用顺序。因此不建议使用它来做关闭资源之类的工作。finalize能做的所有事情,try-catch都能做的更好、更及时,我们可以完全忘掉Java中此方法的存在。

至于上图中的“执行 GC ”过程,请看接下来的垃圾收集算法篇。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值