如何判断一个对象死亡?
当一个对象已经不再被任何的存活对象继续引用时(即没人用),就可以宣判为已经死亡。
判断对象存活的算法一般有两种:引用计数算法和可达性分析算法
请问什么是引用计数算法
引用计数算反(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引用数为1Test01 a=new Test01();//b引用实例b,所以实例b引用数为1Test01 b=new Test01();//二:相互引用//a.obj引用了实例b,故实例b引用数+1=2a.obj=b;//b.obj引用了实例a,故实例a引用数+1=2b.obj=a;//三:删除引用//删除a引用实例a,故实例a引用数-1=1a=null;//删除b引用实例b,故实例b引用数-1=1b=null;//四:垃圾清除,如果采用引用算法的话,会导致内存无法释放。System.gc();}}
