对象已死吗

在堆里面存放着 Java 世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”。

前言

一本好书,每读一遍都会有不同的感受。写读书笔记,一来是便于平时查阅,毕竟技术书籍都比较厚,不方便随时携带;二来是督促自己多读书,理论与实践结合才能不断提升自己。

【深入理解Java虚拟机】阅读笔记: 3.2 对象已死吗

引用计数法

  • 实现简单,判定效率高
  • 很难解决对象之间相互循环引用的问题
  • 主流的 Java 虚拟机未采用

引用计数算法的缺陷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* testGC() 方法执行后,objA 和 objB会不会被 GC 呢?
*
* VM Args: -XX:+PrintGCDetails
*/
public class ReferenceCountingGC {

public Object instance = null;

private static final int _1MB = 1024 * 1024;

/**
* 这个成员属性的唯一意义就是占内存,以便能在 GC 日志中看清楚是否被回收过
*/
private byte[] bigSize = new byte[2 * _1MB];

public static void main(String[] args) {
testGC();
}

public static void testGC() {
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA;

objA = null;
objB = null;

// 假设在这行发生 GC,objA 和 objB 是否能被回收?
System.gc();
}
}

可达性分析算法

主流的商用程序语言的主流实现中使用可达性分析 (Reachability Analysis) 来判定对象是否存活

可达性分析算法判定对象是否可回收

Java 可作为 GC Roots 的对象

  • 虚拟机栈 (栈帧中的本地变量表) 中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中 JNI (Native方法) 引用的对象

Java 引用

  • 强引用 (Strong Reference)。类似 “Object obj = new Object()” 的引用。垃圾收集器不回收强引用的对象
  • 软引用 (Soft Reference)。使用 SoftReference 类来实现软引用。在系统将要发生内存溢出异常之前对这些对象进行回收
  • 弱引用 (Weak Reference)。使用 WeakReference 类来实现弱引用。在下一次垃圾收集时,无论内存是否足够都会回收这部分对象
  • 虚引用 (Phantom Reference)。使用 PhantomReference 类来实现虚引用。无法通过虚引用获取对象实例。不影响对象生存时间

参考

周志明. 深入理解Java虚拟机