在堆中存放着对象实例,GC回收器在对堆进行回收前,需要确定哪些对象需要被回收,即确定哪些对象还存活,哪些对象已经死去(即不可能在被任何途径使用的对象)
——引用计数法
前言:给对象添加一个引用计数器,每当一个地方引用它时,计数器加1,每当引用失效时,计数器减少1.当计数器的数值为0时,也就是对象无法被引用时,表明对象不可在使用,这种方法实现简单,效率较高,大部分情况下不失为一个有效的方法。但是主流的Java虚拟机如HotSpot并 没有选取引用计数法 来回收内存,主要的原因难以解决对象之间的相互循环引用的问题
反例演示
创建2个对象实例,他们相互引用对方 objA.instance=objB objB.instance=objA
而后objA=null objB=null 使得无法访问到堆中对象,但是由于objA objB还相互引用
根据 引用计数法 GC无法回收它们,
public class ReferenceCountingGC {
private Object instance=null;
private static final int _1MB=1024*1024;
private byte[] bigSize=new byte[1024*1024];//1MB的堆空间
public static void main(String[] args) {
// TODO Auto-generated method stub
ReferenceCountingGC objA=new ReferenceCountingGC();
ReferenceCountingGC objB=new ReferenceCountingGC();
//objA 和 objB相互引用
objA.instance=objB;
objB.instance=objA;
objA=null;
objB=null;
System.gc();//调用GC
}
}
Eclipse配置虚拟机启动参数 Args: -XX:+PrintGCDetails 打印GC 日志
运行结果:
根据GC日志可以看到 PSYoungGen: 4014K->664K
也就是新生代(堆中新创建的对象) 被回收了,成功将无法访问到的对象回收了
侧面说明Java虚拟机并不是采用引用计数法 确定需要回收的对象