【问题标题】:Watching the garbage collector bin an object观察垃圾收集箱中的一个对象
【发布时间】:2012-01-28 12:36:28
【问题描述】:

我试图查看垃圾收集器何时“垃圾收集”一个对象。根据文档,当垃圾收集器“删除”一个对象时,会调用一次 finalize() 方法。

我试图覆盖 finalise() 以查看在我使对象无效后是否可以看到它在什么时候被调用,但我似乎在无限期地等待。这应该有效吗?

class Dog{
    ZiggyTest2 z;
    public Dog(ZiggyTest2 z){
        this.z = z;
    }

    protected void finalize() throws Throwable {
        try {
            synchronized(z){
                System.out.println("Garbage collected");
                z.notify();
            }
        } finally {
            super.finalize();
        }
    }
}

还有主类:

class ZiggyTest2{

    public static void main(String[] args){

    ZiggyTest2 z = new ZiggyTest2();        
    Dog dog = new Dog(z);   

        synchronized(z){
            try{
                dog = null;
                z.wait();
            }catch(InterruptedException ie){
                System.out.println("Interrupted");
            }           
        }
    }   
}

我想做的是在我使 Dog 对象无效后看到 finalise() 方法被调用。这就是为什么我将 notify() 语句放在 finalize() 方法中的原因。它不起作用,它只是一直在等待..

编辑

谢谢各位。在我修改 ZiggyTest2 添加 System.gc();

class ZiggyTest2{

    public static void main(String[] args){

    ZiggyTest2 z = new ZiggyTest2();        
    Dog dog = new Dog(z);   

        synchronized(z){
            try{
                dog = null;
                System.gc();
                z.wait();
            }catch(InterruptedException ie){
                System.out.println("Interrupted");
            }           
        }
    }   
}

输出:

C:\>java ZiggyTest2
Garbage collected

【问题讨论】:

  • 您应该尝试手动调用 GC (System.gc()),但即便如此,Java 的 GC 也不是确定性的,并且命令不会强制它唤醒。无法知道对象是否以及何时被收集,也无法确保调用“finalize”方法。

标签: java multithreading garbage-collection scjp


【解决方案1】:

嗯,首先不能保证垃圾收集器何时运行以及将收集什么。收集器很可能不会在您的示例中运行,因为还有大量可用内存。您可以使用System.gc(),但不能保证这会真正触发收集器,它只是向 JVM 提示您希望它运行垃圾收集器。

此外,finalize() 每个实例只会运行一次,即当finalize() 阻止对象被回收时,任何进一步的垃圾回收运行都不会再次调用finalize(),但它可能会回收对象。

【讨论】:

    【解决方案2】:

    垃圾收集器仅在需要时运行。如果您的程序不需要执行 GC,它可以在没有 GC 的情况下运行一整天。您可以调用 System.gc() 来尝试触发 GC。

    注意:如果你有一个 finalize 方法,gc 不会等待在后台线程中调用 finalize 方法,因此对象可能存在,直到 GC AFTER finalize 被调用。

    【讨论】:

      【解决方案3】:

      在设置 dog = null 后尝试添加System.gc()

      【讨论】:

      • 是的,只要我在 dog==null 之后添加 System.gc() 就可以了!它立即收集了垃圾。我知道垃圾收集器有自己的想法,但只是想看看我是否可以触发它。谢谢
      • @ziggy 垃圾收集器仍然有自己的想法,但你可以要求它运行——如果它喜欢你,它就会这样做。 :)
      猜你喜欢
      • 1970-01-01
      • 2011-07-16
      • 2010-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多