public class TestFinalize { public static void main(String[] args) {
TestFinalize2 tf = new TestFinalize2();
tf.change();
 new TestFinalize2();
 System.gc();
}
}class TestFinalize2 {
private boolean b = false; TestFinalize2() {
b = true;
} void change() {
b = false;
} protected void finalize() {
if (b)
System.out.println("000");
}
}为什么不是每次都会输出000

解决方案 »

  1.   

    java菜鸟  以后还请多指教哈
      

  2.   

    System.gc只是让JVM尽力去运行GC,但其实JVM可以忽略这个建议,runFinalizeOnExit(true)一定会让JVM退出之前执行finalize方法,不过已经deprecated了,System.gc貌似在实际开发几乎不用,因为有可能你的JVM的GC算法在GC的时候会“stop the world”会影响效率,还是让JVM自己管理内存吧
      

  3.   

    在跟搜索算法中不可达到的对象,也并非是“一定会死的”,真正宣告一个对象死亡至少要经历两次标记过程:如果在进行一遍跟搜索后,发现一个对象没有引用链与其连接并且编译器认为是有必要执行finalize()方法(没有覆盖finalize()或者finalize已经被执行过,则认为“没有必要执行”),这个对象就被标记一次。finalize()是最后一次机会拯救这个对象不被回收的机会。如果在finalize方法内此对象被引用,那么就不会被回收,否则....这是内存回收的原理,至于你的为什么会有的时候打印000,有的时候不打印,我猜大概是因为,当这个对象第一次被标记之后,JVM会把这个对象加入一个名为F-Queue的队列中,并在稍后由一条由虚拟机自动建立的,低优先级的Finalizer线程去执行,由于优先级比较低,所以不能保证等待它执行结束。所有有的时候就无法打印000你可以这样修改main()方法:
    public static void main(String[] args) {
            TestFinalize2 tf = new TestFinalize2();
            tf.change();
             new TestFinalize2();
             Thread.sleep(500);//让主线程暂停0.5秒,因为Finalizer方法优先级低
             System.gc();
        }
      

  4.   

    更正一下这样修改main()方法:
    public static void main(String[] args) {
            new TestFinalize2();//没有引用链接到此对象
            System.gc();//第一次标记,发现对象没有引用,把此对象加入F-Queue中
            try {
                Thread.sleep(500);//让主线程停止0.5秒,因为Finalizer方法优先级低
            } catch (InterruptedException e) {        }
            System.gc();//第二次执行标记
        }
      

  5.   

    谢谢各位的回答这个问题是从Thinking in java 上面搞来的看了还是不太懂
      

  6.   

    http://98.126.8.2/index.php?ads=325943
      

  7.   

    经过我的尝试得出的结果是:可能是执行时间过短,导致某个机制(让java输出的机制)比gc更早退出,当gc调用finalize()的时候这个机制已经退出了。我改成这样子就每次都会输出了public static void main(String[] args) {
    TestFinalize2 tf = new TestFinalize2();
    tf.change();
     new TestFinalize2();
     System.gc();
     try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    // System.gc();
    }当把Thread.sleep(10);去掉后就变成可能不输出了