本人最近在学JVM,学习GC时,发现一道不错的题目,故此拿出来与大家一起分享。
public class ReliveObj {
public static ReliveObj obj;
@Override
protected void finalize() throws Throwable {
super.finalize();
obj = this;
}
@Override
public String toString() {
return "I am a ReliveObj";
}
public static void main(String[] args) throws InterruptedException {
obj = new ReliveObj();
System.out.println(obj);
obj = null;
System.out.println(obj);
System.gc();
TimeUnit.SECONDS.sleep(1);
System.out.println(obj);
obj = null;
System.out.println(obj);
System.gc();
TimeUnit.SECONDS.sleep(1);
System.out.println(obj);
}
}
问输出是什么,大家不妨试下,看看能不能做对,稍后公布答案
http://blog.csdn.net/z_dendy/article/details/12955677
跑一遍不就知道了,能不动脑就不动脑
这里我直接给答案吧
I am a ReliveObj //很显然
null //obj被置位Null,obj引用已经不指向new出来的那块内存空间
I am a ReliveObj //这里强制触发了垃圾回收,系统会调用finalize函数,可见,obj=this,obj又获得了引用,所以强烈推荐不使用finalize函数,极易造成内存泄漏
null //这里obj被置null
null //这里再次触发垃圾回收,但是finalize函数只会被触发一次,所以空间被彻底释放了
最近在学JVM,有兴趣的同学可以在我私人博客shinerio.cc留言,大家一起探讨进步
null //这里再次触发垃圾回收,但是finalize函数只会被触发一次,所以空间被彻底释放了。
这个解释不够精确吧,感觉应该是GC认为该对象已经被回收了,而实际上未被回收,所以不再调用finalize(),这样才能解释内存泄露;
如果空间被彻底释放了,那就不叫内存泄露了,被释放的内存还能够被分配给其他对象。
首先,楼主的分享精神很好,建议你写一篇分享博客,而不是在这个问答频道提问题。
其次,System.gc()并不一定是让JVM立即执行垃圾回收,只是一种建议行为但是不一定能得到理解执行,而且可能会降低垃圾回收的效率。
我们编码过程中需要考虑释放内存,是在一个方法计算时间较长,前面定义的对象再后面的操作中不会再使用的情况下及时设置为null,可以让JVM及时进行内存回收。
但是对通常的短时间的操作完全没有必要考虑这种问题,方法调用完成后,JVM会自动进行内存回收的。