【问题标题】:Java finalizer guardian does not seem to work?Java 终结器守护者似乎不起作用?
【发布时间】:2011-10-25 20:57:21
【问题描述】:

我有一个带有 finalize() 方法的可伸缩构造函数的超类。为了防止子类忘记调用 super.finalize,我编写了一个像这样的终结器守护程序(EJ Item 7)。

public class Super {

    public Super() {}

    {
        Object finalizerGuardian = new Object() {
            @Override
            protected void finalize() {
                System.out.println("Finalizer guardian finalize");
                Super.this.finalize();
            }
        };
    }

    protected void finalize() {
        System.out.println("Super finalize");
    }

}

这是一个示例子类 --

public class Sub extends Super {

    public Sub() {}

    protected void finalize() {
        System.out.println("Sub finalize");
    }

    public static void main(String[] args)
            throws InterruptedException {
        if (1 == 1) {
            Sub s1 = new Sub();
        }
        Runtime.getRuntime().gc();
        Thread.sleep(10000);
    }
}

当 s1 对象超出范围时,终结器监护人的 finalize() 被调用,我从子类的 finalize 方法中获取 SYSO,但从未从 super 的 finalize 中获取。

我很困惑。我从根本上误解了什么吗?

免责声明:我意识到终结器是危险的并且不可取,等等。仍然试图理解这里的问题。

【问题讨论】:

    标签: java finalize


    【解决方案1】:

    有效的 Java 的终结器守护者应该自己执行必要的终结逻辑(例如,调用执行实际终结的 Super 的某些方法)而不是调用 finalize() 方法,因为在您的情况下,Super.this.finalize(); 实际上调用子类中的重写方法。

    还要注意终结器守护者应该是类的一个字段:

    public class Super {
        private final Object finalizerGuardian = new Object() {
                @Override
                protected void finalize() {
                    Super.this.doFinalize();
                }
        };
    
        private void doFinalize() {
            System.out.println("Super finalize");
        }
    }
    

    【讨论】:

    • 太沉迷于“它不起作用”,看不到明显的问题。谢谢!!
    【解决方案2】:

    您正在重载Sub 中的Super.finalize() 方法。这就是为什么它没有被调用。

    因此,当您在“finalizerGuardian”中调用Super.this.finalize(); 时,您实际上是在调用Sub.finalize()

    【讨论】:

      【解决方案3】:

      正如其他人已经说过动态调度是您的问题。但是据我所知,您的代码中还有另一个主要错误:您的 finalizerGuardian 仅在初始化块内定义,这意味着一旦对象被初始化,对象就会超出范围并且可以被 GC。

      也就是说,即使您解决了第一个问题(通过在您的类中定义一个处理终结内容的 final 方法),您仍然需要将 finalizerGuardian 保存在一个实例变量中。

      【讨论】:

        【解决方案4】:

        Super.finalize() 没有被调用,因为 Sub 覆盖了它。尝试添加一个Super._finalize() 方法并从Super.finalize() 和终结器守护者调用它。

        另外,我认为finalizerGuardian 需要是Super 的字段。否则,即使 Super 对象仍然是强可达的,它也会被垃圾回收。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-12-02
          • 2019-11-22
          • 1970-01-01
          • 1970-01-01
          • 2013-03-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多