Java终结器守护者似乎不起作用?

发布于 2024-11-29 10:15:00 字数 1106 浏览 2 评论 0原文

我有一个带有带有 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,但永远不会从超级的 Finalize 中获取 SYSO。

我很困惑。我是否从根本上误解了某些东西?

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

I have a super class with telescoping constructors with a finalize() method. To protect against subclasses forgetting to invoke super.finalize, I have written a finalizer guardian (EJ Item 7 ) like so.

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");
    }

}

Here is a sample subclass --

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);
    }
}

When the s1 object goes out of scope, the finalizer guardian's finalize() gets called, and I get the SYSO from the subclass's finalize method, but never get the one from super's finalize.

I'm confused. Am I misunderstanding something fundamentally?

Disclaimer : I realize finalizers are dangerous and not advisable, etc. Still trying to understand the problem here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

待天淡蓝洁白时 2024-12-06 10:15:00

有效的 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");
    }
}

Effective Java's finalizer guardian should perform the necessary finalization logic itself (for example, call some method of Super that performs the actual finalization) rather than call the finalize() method, because in your case Super.this.finalize(); actually calls the overriden method from the subclass.

Also note that finalizer guardian should be a field of the class:

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

    private void doFinalize() {
        System.out.println("Super finalize");
    }
}
女中豪杰 2024-12-06 10:15:00

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

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

You are overloading the Super.finalize() method in Sub. That's why it's not being called.

So when you in "finalizerGuardian" call Super.this.finalize(); you are actually calling Sub.finalize().

紫竹語嫣☆ 2024-12-06 10:15:00

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

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

AS others have already said dynamic dispatch is your problem here. BUT there's one other major bug in your code as far as I see: Your finalizerGuardian is only defined inside the initialization block, this means that as soon as the object is initialized, the object gets out of scope and can be GCed.

Ie even if you fix your first problem (by defining a final method in your class that handles the finalization stuff), you'll still need to save the finalizerGuardian in a instance variable.

眉目亦如画i 2024-12-06 10:15:00

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

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

Super.finalize() is not getting called because Sub overrides it. Try adding a Super._finalize() method and calling it from Super.finalize() and the finalizer guardian.

Also, I think finalizerGuardian needs to be a field of Super. Otherwise, it can get garbage collected even if the Super object is still strongly reachable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文