为什么没有调用 finalize?

2022-09-04 02:44:39

我有几个关于java中的垃圾回收器的问题。

Q1.As 据我所知,当对象超出范围并且JVM即将收集垃圾时,finalize()被调用。我以为finize()方法是由垃圾回收器自动调用的,但它在这种情况下似乎不起作用。这是什么解释?为什么我需要显式调用finize()方法?

public class MultipleConstruct {
    int x,y;    
    public MultipleConstruct(int x)
    {
        this.x= x;
        y=5;        
        System.out.println("ONE");
    }

    @Override
    protected void finalize() throws Throwable {
        // TODO Auto-generated method stub
        super.finalize();
        System.out.println("FINALIZED");
    }
    public static void main(String[] args) throws Throwable {
        MultipleConstruct construct = new MultipleConstruct(3);
    }
}

问题 2.另外,何时调用垃圾回收器?我知道gc是一个守护进程线程,由JVM调用,具体取决于剩余的堆大小。这是否意味着,JVM 等待程序使用资源的阈值限制,然后通知 gc 清除垃圾对象。

编辑:gc 如何解析循环引用?


答案 1

有很多finize()方法,坦率地说,这需要写很多,但简而言之:

如果对象在运行其 finalize 方法(如果有)后仍无法访问,则该对象处于最终状态。已定型的对象正在等待解除分配。请注意,VM 实现控制何时运行终结器。你几乎总是最好自己清理,而不是依靠终结器。使用终结器还会留下在不确定时间内无法恢复的关键资源。

在你的情况下,它不打印的原因是你不知道终结器线程何时会调用finize()方法。正在发生的事情是,在打印任何内容之前,程序正在终止。要检查它:编辑主代码中的代码(注意:这不能保证也不应该依赖它,但它仍然会打印一些时间)

for(int i =0;i<1000000;i++)
    {
        MultipleConstruct construct = new MultipleConstruct(3);
        construct = null;
    }

使用finize()有很多缺点,从在对象构造中花费更多时间到内存泄漏和内存匮乏的可能性。如果你在finize()中强烈引用相同的对象,那么它永远不会被第二次调用,因此可以使系统处于不需要的状态等等。你应该使用finize()的唯一地方是作为一个安全网来处置任何资源,比如InputStream用它来关闭(同样,不能保证它会在你的程序还活着的时候运行)。使用它的另一个地方是在使用垃圾回收器无法控制的本机时。

欲了解更多信息,请访问:

http://jatinpuri.com/?p=106


答案 2

q1) finalize 方法在垃圾回收对象时被调用,因此,如果没有执行 GC,则可能不会调用终结器。您需要简单地调用 super 来保留 Object 实现提供的行为。

q2)执行GC的确切时刻取决于许多因素,例如:您正在使用的JVM,调整参数,可用堆的数量等。因此,它不仅依赖于已用堆阈值。您也可以要求通过 System.gc() 执行 GC,但您不能保证是否以及何时实际执行。您可以在 http://java.sun.com/performance/reference/whitepapers/tuning.html 中找到有关如何配置GC的更多详细信息