在Java中,是否有可能确定一个对象是否被垃圾收集器回收了?

6

我读到过这样的内容,即对象在以下情况下变得适合进行垃圾回收:

  1. 该对象的所有引用都显式设置为null。
  2. 对象在块中创建,一旦控制退出该块,引用就会超出范围。
  3. 父对象设置为null,如果一个对象持有另一个对象的引用,并且当您将容器对象的引用设置为null时,子对象或包含的对象自动变为适合进行垃圾回收。

但是,有没有办法确定适合进行垃圾回收的对象是否被垃圾回收器收集了?


1
你需要知道这个的原因是什么?有具体的原因吗? - kosa
2
只要您在引用对象(直接或间接地),它就不会成为垃圾回收的候选对象。因此,当它最终被垃圾回收时,您将不再拥有对它的引用,这意味着您无法识别它 - 您必须完全忘记它,否则它将不会被垃圾回收。 - Guntram Blohm
@Nambari.. 我正在阅读有关垃圾收集器工作的文章,这个问题在我的脑海中浮现出来。 没有其他原因。 - Dhruv Kapatel
像其他人说的一样:你唯一的选择是使用finalize方法。然而,我必须告诉你:我写了成千上万行Java代码,从来没有遇到过需要使用finalize的情况。在与其他程序员交流时,它从未被提及。除了满足你对它的好奇心之外,我强烈建议不要使用这个方法。我真的不知道为什么他们不废弃它... - Radu Murzea
@RaduMurzea:虽然它们非常罕见,但有一些finalize方法的好用途 - maaartinus
2个回答

4
你可以实现Object#finalize()方法。
public class Driver {
    public static void main(String[] args) throws Exception {
        garbage();

        System.gc();
        Thread.sleep(1000);
    }

    public static void garbage() {
        Driver collectMe = new Driver();
    }

    @Override
    protected void finalize() {
        System.out.println(Thread.currentThread().getName() + ": See ya, nerds!");
    }
}

打印的功能

Finalizer: See ya, nerds!

所以您可以在收集之前拦截。 javadoc指出:
finalize的一般契约是,如果且仅当JavaTM虚拟机已经确定不再有任何方法可以通过尚未死亡的任何线程访问此对象,除非由于其他对象或类的完成采取的操作而导致,那么它将被调用。 准备完成。finalize方法可以采取任何操作,包括再次将此对象提供给其他线程;
但也是这样:
对于任何给定的对象,finalize方法最多只会被Java虚拟机调用一次。

2

对象被垃圾回收后,JVM会调用它的finalize方法。默认实现不做任何事情;您可以覆盖它以打印告别消息或关闭某些已打开的资源。

但请注意,不能保证在收集后多久调用它。


2
你的第一句话是错误的。finalize()方法会在对象被认为可回收时调用,而不是在对象被回收后调用。 - Sotirios Delimanolis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接