java - 为什么不调用 finalize?

标签 java garbage-collection

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

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

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

Q2。另外,什么时候调用垃圾收集器?我知道 gc 是一个守护线程,由 JVM 根据剩余的堆大小调用。那是不是意味着,JVM等待程序使用资源的阈值限制,然后通知gc清理垃圾对象。

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

最佳答案

finalize() 方法有很多内容,坦率地说,要写的内容很多,但简而言之:

如果一个对象在其finalize方法(如果有的话)运行后仍然无法访问,则该对象处于finalized状态。已完成的对象正在等待释放。请注意,VM 实现控制终结器何时运行。你几乎总是最好自己做清理而不是依赖终结器。使用终结器还可以留下在不确定的时间内无法恢复的关键资源。

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

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

使用 finalize() 有很多缺点,从在对象构造上花费更多时间到内存泄漏和内存不足的可能性。如果您在 finalize() 中强烈引用同一个对象,那么它永远不会被第二次调用,因此可能会使系统处于不希望的状态等等...... 您应该使用 finalize() 的唯一地方是作为安全网来处理任何资源,例如 InputStream 使用它来关闭(同样不能保证它会在您的程序仍然存在时运行)。另一个使用它的地方是在垃圾收集器无法控制的情况下使用 natives。

更多信息请访问:

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

关于java - 为什么不调用 finalize?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7786946/

相关文章:

java - 为什么系统会自动将我的 LinkedHashMap 转换为 HashMap,同时将其作为可序列化的 Intent 传递?

java - 即使变量更新, while 循环也不会退出

java - groovy 中的排序 map

Java挂了几秒,但是在gc log中没有发现gc pause

.net - .NET GC 的标记和清理阶段如何与应用程序线程同时运行?

c# - 如何判断对象是否已被垃圾收集

java - 由从未引用的对象创建的垃圾

Java - 有关使用 "split()"的帮助

java - Java 10 上的远程 JProfiler

jakarta-ee - 如何在 Oracle JRE 中跟踪方法 System.gc()