如何判断一个对象死亡?
当一个对象已经不再被任何的存活对象继续引用时(即没人用),就可以宣判为已经死亡。
判断对象存活的算法一般有两种:引用计数算法和可达性分析算法
请问什么是引用计数算法
引用计数算反(Reference Counting)比较简单,对每个对象保存一个整型的引用计数属性,用于记录对象被引用的情况。
对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1;当引用失效时,引用计数器就减1.
只要对象A的引用计数器的值为0,即表示对象A不可能再被使用,可进行回收。
该算法的优缺点:
优点:实现简单,垃圾对象便于辨识;判定效率高,回收没有延迟性。
缺点:需要单独的字段存储计数器,这样的做法增加了存储空间的开销。
每次赋值都需要更新计数器,伴随着加法和减法操作,增加了时间的开销。
引用计数器有一个严重的问题,即无法处理循环引用的情况。这是一条致命缺陷,导致Java的垃圾回收器中没有使用这类算法。
- 创建对象a,存储在堆中,main方法的栈帧中的局部变量a引用了堆空间Test01实例a地址。
- 创建对象b,存储在堆中,main方法的栈帧中的局部变量b引用了堆空间Test01实例b地址。
- Test01实例a的obj引用了Test01的实例b地址
- Test01实例b的obj引用了Test01的实例a地址
当执行a=null; b = null;时,就变成如下图,将会导致堆循环相互引用,从而导致gc回收失败。
Java是否用了计数算法?
/**
-Xms30M
-Xmx30M
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-XX:+PrintHeapAtGC
*/
public class Test01 {
private Test01 obj=null;
byte[] bytes = new byte[2*1024*1024];
public static void main(String[] args) {
//一:直接引用
//a引用实例a,所以实例a引用数为1
Test01 a=new Test01();
//b引用实例b,所以实例b引用数为1
Test01 b=new Test01();
//二:相互引用
//a.obj引用了实例b,故实例b引用数+1=2
a.obj=b;
//b.obj引用了实例a,故实例a引用数+1=2
b.obj=a;
//三:删除引用
//删除a引用实例a,故实例a引用数-1=1
a=null;
//删除b引用实例b,故实例b引用数-1=1
b=null;
//四:垃圾清除,如果采用引用算法的话,会导致内存无法释放。
System.gc();
}
}