Java局部变量对垃圾回收的影响

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()的运行结果:



 
 可以看出堆空间几乎没有变化。

猜你喜欢

转载自xigua366.iteye.com/blog/2280696
今日推荐