引用计数算法是常用的内存管理算法,该算法的缺陷是会产生循环引用,导致对象永远不会被回收。下面证明JVM不是通过引用计数算法来判断对象是否存活。
//Debug Configuration:
//-verbose:gc: -Xms20M -Xmx20M -Xmn10M -verbose:gc -XX:+PrintGCDetails -XX:SurvivorRatio=8
public class ReferenceCountingGC {
public Object instance = null;
private static final int _1MB = 1024 * 1024;
private byte[] bigSize = new byte[2 * _1MB];
public static void testGC()
{
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
System.gc();
}
public static void main(String[] args)
{
testGC();
}
}
结果:
[Full GC[Tenured: 0K->376K(10240K), 0.0080588 secs] 4684K->376K(19456K), [Perm : 149K->149K(12288K)], 0.0334432 secs] [Times: user=0.02 sys=0.00, real=0.03 secs]
Heap
def new generation total 9216K, used 327K [0x32f00000, 0x33900000, 0x33900000)
eden space 8192K, 4% used [0x32f00000, 0x32f51f90, 0x33700000)
from space 1024K, 0% used [0x33700000, 0x33700000, 0x33800000)
to space 1024K, 0% used [0x33800000, 0x33800000, 0x33900000)
tenured generation total 10240K, used 376K [0x33900000, 0x34300000, 0x34300000)
the space 10240K, 3% used [0x33900000, 0x3395e090, 0x3395e200, 0x34300000)
compacting perm gen total 12288K, used 149K [0x34300000, 0x34f00000, 0x38300000)
the space 12288K, 1% used [0x34300000, 0x34325638, 0x34325800, 0x34f00000)
ro space 10240K, 44% used [0x38300000, 0x38778300, 0x38778400, 0x38d00000)
rw space 12288K, 52% used [0x38d00000, 0x3934f100, 0x3934f200, 0x39900000)
4684K->376K(19456K)表明,GC发生前,该内存已使用4684K,GC发生后,该内存使用了376K,表明对象已被回收,从而表明JVM没有使用引用计数算法。Java中使用了可达性分析算法来来判定对象是否存活,