This question already has answers here:
Java and manually executing finalize

(3个答案)



When is the finalize() method called in Java?

(17个答案)


6年前关闭。





就我的理解而言,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?


同样,按照docs的规定,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()方法。终结队列是放置准备好要调用finalize()方法的对象的队列。


创建对象时,JVM将检查用户是否覆盖了finalize()方法。如果具有,则在内部指出该特定对象具有finalize()方法。


当对象准备好进行垃圾回收时,垃圾回收器线程会检查该特定对象是否具有(1)中提到的表中的finalize()。


2a)如果没有,则将其发送至垃圾收集。

2b)有,然后将其添加到完成队列。并且它从表(1)中删除对象的条目。


终结器线程不断轮询队列。对于队列中的每个对象,将调用其finalize()方法。在调用finalize()循环之后,再次重复从(2)开始的循环。如果该对象仍然没有强引用,则发送给GC。如果
它具有ALWAYS(2a)的调用,因为该条目已在(2b)中被删除

Basically finalize() method is only called once.


那么上述周期有什么问题?


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

从(2b):内存泄漏和饥饿。如果队列中的对象引用了很多内存资源,那么除非这些对象准备好用于GC,否则所有这些对象都不会被释放;如果所有对象都是重量级的对象,则可能会短缺。

从(2b):因为finalize()仅被调用一次,所以如果在finalize()中您强烈引用了“ this”对象。下次将不再调用对象的finalie(),因此可能会使该对象处于不一致状态。

如果在finalize()内部抛出异常,则将其忽略。


您不知道何时调用finalize(),因为您无法控制何时调用GC。有时,您可能会在finalize()中打印值,但从不显示输出,因为您的程序可能在调用finalize()时就被终止了。

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

关于java - 当我们显式调用finalize()时,是否释放了对象内存? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18510582/

10-12 20:40