可达性分析算法以GC Roots为起点遍历引用链标记存活对象,未被标记的不可达对象可回收;Java四种引用类型按强度排序,强引用永不回收,软引用在内存不足时回收,弱引用在每次GC时回收,虚引用仅用于回收通知。

Java 的可达性分析算法是垃圾回收器判断对象是否存活的核心机制,它不依赖引用计数,而是从一组称为“GC Roots”的对象出发,沿着引用链向下搜索;所有能被访问到的对象视为“可达”,不可达的对象则可能被回收。引用类型则决定了对象在可达性分析中的“强度”——不同引用类型对 GC 的影响不同,直接影响对象何时被回收。
可达性分析算法怎么工作
该算法把堆中所有对象看作图结构的节点,引用关系为有向边。GC Roots 是起点,包括:
- 虚拟机栈(栈帧中的局部变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象(如字符串常量池里的 String)
- 本地方法栈中 JNI(即 Native 方法)引用的对象
- Java 虚拟机内部的特殊对象(如基本类型的 Class 对象、一些常驻异常对象等)
从这些根节点开始遍历,所有能到达的对象标记为“存活”,其余未被标记的对象即为“可回收”。注意:两次标记机制(如 finalize() 的触发)属于后续处理,并非可达性分析本身。
四种引用类型与 GC 行为的关系
Java 提供四种引用类型,按强度从高到低排列,它们决定了对象在 GC 过程中是否被回收:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
强引用(StrongReference)
最常见,如 Object obj = new Object();。只要强引用存在,GC 永远不会回收该对象。即使内存不足抛出 OOM,也不会回收强可达对象。
软引用(SoftReference)
用于实现内存敏感的缓存。只有当 JVM 认为内存不足(即将发生 OOM 前)时,才会回收软引用指向的对象。使用方式:SoftReference<Object> ref = new SoftReference<>(new Object());
弱引用(WeakReference)
比软引用更“弱”,GC 线程每次运行时,都会回收只被弱引用关联的对象(无论内存是否充足)。适合构建非强制缓存或监听器自动清理场景。使用:WeakReference<Object> ref = new WeakReference<>(new Object());
虚引用(PhantomReference)
最弱,无法通过它获取对象实例。唯一作用是在对象被 GC 回收前收到系统通知(需配合 ReferenceQueue)。常用于跟踪对象被回收的时间,执行资源清理。使用必须传入队列:PhantomReference<Object> ref = new PhantomReference<>(obj, queue);
实际写法示例(含关键细节)
写引用类型时要注意几点:
- 避免直接用 get() 后不判空——软/弱/虚引用的 get() 可能返回 null
- 软引用不是“内存够就不回收”,JVM 会根据堆剩余空间和最近使用情况综合判断
- 弱引用对象在下一次 GC 就可能消失,不能用于需要稳定生命周期的场景
- 虚引用必须配合 ReferenceQueue 使用,否则无法感知回收事件
- 自定义类中慎用 finalize(),已被标记为废弃,推荐用 Cleaner 或虚引用替代
可达性与引用类型协同工作的典型场景
比如实现一个缓存:
- 用 SoftReference 存储缓存值 → 内存紧张时自动释放
- 缓存 key 用 WeakReference 包装 → 避免因缓存持有 key 导致业务对象无法回收(防止内存泄漏)
- 缓存清理逻辑注册到 ReferenceQueue(配合虚引用或弱引用)→ 及时同步删除过期条目
这种组合既保障了缓存可用性,又兼顾了内存安全性。

















