在堆里面存放着
Java
世界中几乎所有的对象实例
,
垃圾收集器在对堆进行回收前
,
第一件事就是判断哪些
对象已死
(
可回收
).
1
、引用计数法
在
JDK1.2
之前,使用的是引用计数器算法。
在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值就
+1
,当引用失效的时
候,计数器的值就
-1,当引用计数器被减为零的时候,标志着这个对象已经没有引用了,可以回收了!
问题:
如果在
A
类中调用
B
类的方法,
B
类中调用
A
类的方法,这样当其他所有的引用都消失了之后,
A
和
B
还有
一个相互的引用,也就是说两个对象的引用计数器各为
1
,而实际上这两个对象都已经没有额外的引用,
已经是垃圾了。但是该算法并不会计算出该类型的垃圾。
2
、可达性分析法
在主流商用语言
(
如
Java
、
C#)
的主流实现中
,
都是通过可达性分析算法来判定对象是否存活的
:
通过一系
列的称为
GC Roots
的对象作为起点
,
然后向下搜索
;
搜索所走过的路径称为引用链
/Reference Chain,
当
一个对象到
GC Roots
没有任何引用链相连时
,
即该对象不可达
,
也就说明此对象是不可用的
,
如下图
:
虽然
E
和
F
相互关联, 但它们到
GC Roots
是不可达的
, 因此也会被判定为可回收的对象。
注
:
即使在可达性分析算法中不可达的对象
, VM
也并不是马上对其回收
,
因为要真正宣告一个对象死亡
,
至
少要经历两次标记过程
:
第一次是在可达性分析后发现没有与
GC Roots
相连接的引用链
,
第二次是
GC
对
在
F-Queue
执行队列中的对象进行的小规模标记
(
对象需要覆盖
finalize()
方法且没被调用过
).