看下面这个程序,空间竟然没有释放。
手动触发Full GC那么将其赋值为null再看结果,此时发现空间释放出来了。
将对象赋值为空,手动触发Full GC方法在执行的时候,方法里的变量(局部变量)都是分配在栈上的;当然,对于Java来说,new出来的对象是在堆中,但栈中也会有这个对象的指针,和int一样。只要堆中的这个对象,在栈中还存在引用,就会被认定是存活的。代码在离开if后,虽然已经离开了placeHolder的作用域,但在此之后,没有任何对运行时栈的读写,placeHolder所在的索引还没有被其他变量重用,所以GC判断其为存活。
param引用了placeHolder在栈中的位置从运行时栈来看,加上int param= 1;和将placeHolder赋值为null起到了同样的作用:断开堆中placeHolder和栈的联系,让GC判断placeHolder已经死亡。
现在算是理清了“不使用的对象应手动赋值为null“的原理了,一切根源都是来自于传说中的JVM的一个“bug”:代码离开变量作用域时,并不会自动切断其与堆的联系。
补充:配置参数展示GC日志
-XX:+PrintGC 输出GC日志
-XX:+PrintGCDetails 输出GC的详细日志
-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
-Xloggc:../logs/gc.log 日志文件的输出路径
网友评论