Java中的对象引用与可达性分析算法详解
字数 982 2025-11-08 10:03:28
Java中的对象引用与可达性分析算法详解
描述
在Java内存管理中,判断对象是否存活的依据不是引用计数,而是通过可达性分析(Reachability Analysis)算法。该算法通过一系列称为"GC Roots"的根对象作为起始点,从这些节点向下搜索,所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,这个对象就是不可达的,可以被回收。
GC Roots的对象类型
- 虚拟机栈中引用的对象(栈帧中的局部变量表)
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI引用的对象
- Java虚拟机内部的引用(基本类型对应的Class对象等)
可达性分析的具体过程
第一步:枚举根节点
- 虚拟机需要暂停所有执行线程(Stop The World)
- 通过OopMap数据结构快速定位到GC Roots
- 避免在整个堆中查找引用,提高效率
第二步:构建引用链
- 从每个GC Root出发,深度优先或广度优先遍历引用关系
- 标记所有被直接或间接引用的对象为存活对象
- 未被标记的对象即为可回收对象
对象引用状态的变化过程
- 强引用(Strong Reference):最常见的引用,只要强引用存在,对象永远不会被回收
- 软引用(Soft Reference):内存不足时会被回收,适合实现内存敏感的缓存
- 弱引用(Weak Reference):无论内存是否充足,下次GC时都会被回收
- 虚引用(Phantom Reference):最弱的引用,主要用于对象回收跟踪
实际回收判断流程
第一次标记:如果对象没有覆盖finalize()方法或已被调用过,直接回收
第二次标记:如果对象重写了finalize()方法且未被调用过,将其放入F-Queue队列
Finalizer线程异步执行finalize()方法,对象可以在该方法中"自救"
如果对象在finalize()中没有重新建立引用,则最终被回收
算法优化技术
- 卡表(Card Table):减少老年代到新生代的引用扫描
- 记忆集(Remembered Set):记录跨代引用关系
- 三色标记法:并发标记时保证正确性的算法
- 白色:未被访问的对象
- 灰色:已被访问但引用未完全扫描
- 黑色:已被访问且引用完全扫描
通过这种严谨的可达性分析,JVM能够准确判断对象的存活状态,为垃圾回收提供可靠依据。