Java 当我们显式调用finalize()时,对象内存是否被释放?

Java 当我们显式调用finalize()时,对象内存是否被释放?,java,garbage-collection,jvm,finalizer,Java,Garbage Collection,Jvm,Finalizer,就我的理解而言,finalize()和GC是两个不同的方面。GC使用finalize()方法释放对象内存。我们无法说明何时将发生GC(即使显式调用System.GC())。但是我们可以对对象显式调用finalize() Will the function be executed immediately(memory freed) or it waits till GC occurs like System.gc() call? 另外,根据文档,Java虚拟机对任何给定对象调用finalize方

就我的理解而言,finalize()和GC是两个不同的方面。GC使用finalize()方法释放对象内存。我们无法说明何时将发生GC(即使显式调用System.GC())。但是我们可以对对象显式调用finalize()

Will the function be executed immediately(memory freed) or it waits till GC
occurs like System.gc() call?
另外,根据文档,Java虚拟机对任何给定对象调用finalize方法的次数不会超过一次

那么,当我们首先调用finalize()并在稍后的时间点执行GC时会发生什么呢

If object memory is not freed on explicit call to object.finalize() then would't 
it being called again in the GC process violate the calling only once rule? 

你完全弄错了

简短答复:
finalize()
是一种在对象准备进行垃圾收集之前(当没有对象对其具有强引用时)清理资源(如打开的文件)的方法。它可能被称为/不被称为。这比内存释放提前了一步

长答覆:

有一个单独的守护进程线程称为finalizer线程,负责调用finalize()方法。Finalization queue是放置准备好调用finalize()方法的对象的队列

  • 创建对象时,JVM检查用户是否重写了finalize()方法。如果有,那么它会在内部注意到这个特定对象有finalize()方法 当一个对象准备好进行垃圾收集时,垃圾收集器线程检查这个特定对象是否具有(1)中提到的表中的finalize()

    • 2a)如果没有,则发送垃圾回收

      2b)它是has,然后它被添加到终结队列中。并从表(1)中删除对象的条目

    终结器线程继续轮询队列。对于队列中的每个对象,都会调用其finalize()方法。调用finalize()后,再次重复(2)中的循环。如果此对象仍然没有强引用,则发送给GC。如果 由于条目在(2b)中被删除,因此始终调用(2a)

    那么,上述周期的问题是什么

    从(1)开始。它需要额外的时间来创建对象。Java中的内存分配比malloc/calloc等快5到10倍。所有获得的时间都浪费在记录表中对象等过程中。我曾经尝试过。在一个循环中创建100000个对象,并在两种情况下测量程序终止所需的时间:一种是没有finalize(),另一种是finalize()。发现速度快了20%

    来自(2b):内存泄漏和饥饿。如果队列中的对象引用了大量内存资源,则除非该对象已准备好进行GC,否则所有这些对象都不会被释放。如果所有对象都是重量级对象,则可能存在内存不足

    来自(2b):因为finalize()只被调用一次,所以如果在finalize()中有一个对“this”对象的强引用会怎么样。下次永远不会调用对象的finalie(),因此可能会使对象处于不一致的状态

    如果在finalize()内部引发异常,则会忽略它

    您不知道何时调用finalize(),因为您无法控制何时调用GC。有时可能会出现这样的情况:您正在finalize()中打印值,但输出永远不会显示,因为在调用finalize()时,您的程序可能已经终止

    因此,避免使用它。而是创建一个方法,比如dispose(),它将关闭必要的资源或用于最终日志等。

    对于任何给定对象,Java虚拟机都不会多次调用finalize方法


    但是,您不能强制GC运行,您可以通过
    System.GC()
    请求它。所以,最好的方法是在重写时将释放资源的代码放入
    finalize()
    方法。

    答案在Object.finalize API中

    1) GC调用finalize(),因此finalize()和GC不是两个不同的方面

    2) 您不应该手动调用finalize,但如果您这样做,它将不会释放任何内存,也不会影响GC行为


    3) 据说GC保证不会调用finalize两次,我们的调用不算

    @duffymo不算太多…因此我们不能对任何对象显式调用finalize(),即使我们这样做,它也只会在GC发生时执行。是吗?如果你想打电话,你就一直打。但这根本不可取。如果您调用它,它将像任何其他方法调用一样执行。GC调用稍后会调用它(尽管它可能会出现,也可能不会出现)。阅读上面的更多内容info@Jatin-+1(特别是第一句),但请检查我的编辑。您描述了finalize()的功能,我描述了为什么有人认为他们需要它。语句“JVM检查对象是否有finalize()方法”是什么意思?所有对象都有finalize()方法,因为所有扩展对象类都有finalize()方法?该规范有一个“普通”finalizer的概念,即a)由
    java.lang.Object
    声明的
    finalize()
    方法,b)空的
    finalize()
    方法,或c)由唯一的
    super.finalize()组成的
    finalize()
    调用另一个简单的finalize方法。因此,当一个对象被创建时,JVM会检查它的类是否有一个finalize方法是“不平凡的”。仍然依赖于JVM,但这基本上就是答案
    Basically finalize() method is only called once.