1.引用计数法
引用计数法是历史最悠久的一种算法,最早George E.Collins 在1960的时候首次提出,50年后的今天,该算法依然被很多编程语言使用。
1.1原理
假设有一个对象A,任何一个对象对A的引用,那么对象A的引用计数器+1,当引用失败时,对象A的引用计数器就-1,如果对象A的计数器的值为0,那说明对象A没有引用了,可以被回收。
1.2 优缺点
优点:
- 实时性较高,无需等到内存不够的时候才开始回收,运行是根据对象的计数器是否为0,就可以直接回收。
- 在垃圾回收过程中,应用无需挂起,如果申请内存时,内存不足,立刻报outofmemory错误
- 区域性,更新对象的计数器时,只是影响到该对象,不对扫描全部对象。
缺点:
- 每次对象被引用时,都需要去更新计数器,有一点时间开销。
- 浪费CPU资源,即使内存够用,仍然在运行时进行计数器的统计。
- 无法解决循环引用的问题(最大的缺点)。
public classMyObject {
public Object ref =null;
publicstaticvoidmain(String[] args) {
MyObject myObject1 =newMyObject();
MyObject myObject2 =newMyObject();
myObject1.ref = myObject2;
myObject2.ref = myObject1;
myObject1 =null;
myObject2 =null;
}
}
从上面的代码可以轻易地发现myObject1与myObject2互为引用,我们知道如果采用引用计数法,myObject1和myObject2将不能被回收,因为他们的引用计数无法为零。
但是具体是为什么呢?已上图为例,当代码执行完line7时,两个对象的引用计数均为2。此时将myObject1和myObject2分别置为null,以前一个对象为例,它的引用计数将减1。若要满足垃圾回收的条件,需要清除myObject2中的ref这个引用,而要清除掉这个引用的前提条件是myObject2引用的对象被回收,可是该对象的引用计数也为1,因为myObject1.ref指向了它。以此类推,也就进入一种死循环的状态。