试试看,一道充满陷阱的java题目

本人最近在学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会自动进行内存回收的。