如何判断对象是否存活和四种Reference的区别

本文介绍了如何通过可达性分析算法判断对象是否存活,并详细解释了强引用、软引用、弱引用和虚引用的区别及应用场景。
如何判断对象是否存活?

引用计数算法:每引用一次+1,失去引用-1。
缺点:可以互相引用,JVM不采用。

可达性分析算法:

一系列GC Roots为起始点向下搜索,最后没有和GC Roots相连的就是可回收的对象(不一定会回收,此时处于“缓刑”阶段,至少要经历两次标记过程才能真正宣告一个对象的死亡。第一次标记是对象在进行可达性分析后发现没有与GC Roots相连接的引用链,此时还会进行筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过了,虚拟机将这两种情况都视为“没有必要执行”。如果这个对象被判定为有必须执行,会被放到一个名为F-Queue的队列中,由一个虚拟机自动建立的,低优先级的finalizer线程去执行。finalize()方法是对象逃脱死亡的最后一次机会,稍后GC会对F-Queue中的对象进行第二次标记,如果对象要在finalize()中成功拯救自己,只需要重新与引用链上的任何一个对象建立关系即可,比如把自己赋给某个类或者对象的成员变量,那么第二次标记的时候它将被移除“即将回收”的集合,如果对象这个时候还没有逃脱,那就真的被回收了。这种“拯救”对象的方式代价高昂,不确定性大,不推荐使用)。


四种Reference的区别:

强引用(strong Reference):
代码中普遍存在,类似“Object obj = new Object()”这类的引用,只要强引用还在,
垃圾收集器永远不会回收掉被引用的对象。

软引用(Soft Reference):
描述一些还有用但并非必须的对象。对于软引用关联着的对象,在系统将要发生内存溢出
异常之前,将会把这些对象列进回收范围进行第二次回收。如果这次回收还没有足够的内
存,则会抛出内存溢出异常。

弱引用(Weak Reference):
也是用来描述非必须的虚,强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次
垃圾收集发生之前,当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用
关联的对象。

虚引用(Phantom Reference):
也成为幽灵引用或者幻影引用,是最弱的一种引用关系。存在的唯一目的就是能在这个对象
被垃圾收集器回收的时候收到一个系统通知。


### JVM 垃圾回收器判断对象可回收性的机制 JVM 的垃圾回收器通过一系列算法条件来判断对象是否可以被回收。这些条件通常基于对象的引用状态以及其在内存中的存活情况。 #### 引用计数法 一种简单的判断对象是否可回收的方式是 **引用计数法**,即为每个对象维护一个引用计数器。当有一个新的引用指向该对象时,计数加一;当某个引用失效时,计数减一。如果计数值降为零,则表示没有任何引用指向此对象,因此它被认为是可回收的[^3]。 然而,这种方法存在循环引用的问题,可能导致某些实际上已经不再使用的对象无法被正确回收。 #### 可达性分析算法 为了克服引用计数法的缺陷,现代 JVM 主要采用 **可达性分析算法**(Reachability Analysis)。这种算法从一组称为“GC Roots”的根节点集合出发,沿着引用链向下搜索所有可达的对象。任何未被引用链触及到的对象都被视为不可达,从而成为候选回收目标[^1]。 常见的 GC Root 类型包括但不限于: - 虚拟机栈中局部变量表内的引用; - 方法区中类静态属性所持有的引用; - 方法区中常量池里的引用; - 本地方法栈中 JNI 所持的引用。 一旦确认某对象不可达,进一步还需要验证是否有其他特殊原因阻止它的立即销毁,比如 finalize() 方法的存在与否及其执行结果可能影响最终决定。 #### 不同类型的引用对回收的影响 除了基本的强引用外,Java 还定义了几种特殊的弱软虚引用形式,它们各自对应着不同强度级别的关联关系,并间接决定了何时适合触发相应的清理动作: - **Soft Reference**: 在内存不足之前不会轻易丢弃此类数据项。 - **Weak Reference**: 即使还有少量可用空间也会尽快处理掉这类实例。 - **Phantom Reference**: 更倾向于配合特定事件通知机制而非直接参与常规意义上的资源管理流程之中。 综上所述,JVM 使用多种技术手段综合评估哪些对象应该进入下一轮清扫范围之内并实际实施操作过程。 ```java // 示例代码展示如何创建不同类型引用 import java.lang.ref.*; public class RefDemo { public static void main(String[] args) throws InterruptedException { Object obj = new Object(); // 创建一个新对象 SoftReference<Object> softRef = new SoftReference<>(obj); WeakReference<Object> weakRef = new WeakReference<>(obj); PhantomReference<Object> phantomRef = new PhantomReference<>(obj, null); obj = null; // 断开原始强引用 System.out.println(softRef.get()); // 输出可能是null或者原对象 System.out.println(weakRef.get()); // 很大概率已经是null System.out.println(phantomRef.get());// 总返回null } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值