public class GcTest { public void localvarGc1() { byte[] a = new byte[6*1024*1024]; System.gc(); } public void localvarGc2() { byte[] a = new byte[6*1024*1024]; a=null; System.gc(); } public void localvarGc3(){ { byte[] a = new byte[6*1024*1024]; } System.gc(); } public void localvarGc4() { { byte[] a = new byte[6*1024*1024]; } int c = 10; System.gc(); } public void localvarGc5() { localvarGc1(); System.gc(); } public static void main(String[] args) { GcTest ins = new GcTest(); ins.localvarGc1(); } }
?
? ? ? ? 在上述代码中,每一个localvarGcN()函数都分配了一块6MB的堆空间,并是用局部变量引用这块空间。
? ? ? ? 在localvarGc1()中,在申请空间后,立即进行垃圾回收,很明显,由于byte数组被变量a引用,因此无法回收这块空间。
? ? ? ? 在localvarGc2()中,在垃圾回收前,先将变量a置为null,使byte数组失去强引用,姑垃圾回收可以顺利回收byte数组。
? ? ? ? 对于localvarGc3(),在进行垃圾回收前,先使局部变量a失效,虽然变量a已经离开了作用域,但是变量a依然存在于局部变量表中,并且也指向这块byte数组,故byte数组依然无法被回收。
? ? ? ? 对于localvarGc4(),在垃圾回收之前,不仅使变量a失效,更是申明了变量c,使变量c复用了变量a之前的栈,由于变量a此时被销毁,姑垃圾回收器可以顺利回收byte数组。
? ? ? ? 对于localvarGc5(),它首先调用了localvarGc1(),很明显,在localvarGc1()中并没有释放byte数组,但在localvarGc1()返回后,它的栈帧被销毁,自然也包含了栈帧中的所有局部变量,故byte数组失去引用,在localvarGc5()的垃圾回收中被回收。
?
? ? ? ?在启动jvm虚拟机的时候可以使用参数-XX:+PrintGC执行上述几个函数,在输出的日志中,可以看到垃圾回收前后堆的大小,进而推断byte数组是否被回收。下面的输出是函数localvarGc4()的运行结果:
?
从日志中可以看到,堆空间从回收前的6809k变为回收后的600k,释放了约6MB空间。进而可以推断,byte数组已被回收释放。
?
下面是函数localvarGc1()的运行结果:
?
?可以看出堆空间几乎没有变化。
?
原文:http://xigua366.iteye.com/blog/2280696