我在很多地方都发现,java中的finalize()方法是在垃圾收集器或System.gc()成功保留了冗余对象消耗的内存而不再引用它时调用的。还发现这个方法被调用的次数不超过一次。我不是 Java 的新手,但也不是很有经验。可能我理解有误但是还是说一段代码吧
public class Solution {
@Override
protected void finalize(){
System.out.print("method called");
}
public static void main(String... args){
Solution obj1= new Solution();
Solution obj2 = new Solution();
Solution obj3 = new Solution();
System.gc();
obj1=obj2;
System.gc();
obj3=null;
System.gc();
}
}
这里,finalize 方法被调用了两次,因为内存堆两次符合垃圾清理条件。所以,我有点困惑我是否知道整个事情是正确的,或者它是否应该按照它的行为方式行事。
最佳答案
没有。 finalize()
方法只会被对象的 GC 调用一次。 JVM 在对象头(我认为)中设置了一个标志,表示它已经完成,并且不会再次完成。
javadoc明确指出:
" The finalize method is never invoked more than once by a Java virtual machine for any given object. "
当然,没有什么可以阻止对象方法多次调用 this.finalize()
。
请注意,由于 javadoc 中所述的原因,finalize()
在 Java 9 及更高版本中被弃用。建议您改为使用以下其中一项:
AutoCloseable
+ 尝试使用资源清洁剂
PhantomReference
有人这样评论:
finalize()
is called for everyObject
that is collected.
由于几个原因,这不是真的。
javadoc 明确声明不保证
finalize
会被调用。可以保证的是,在对象的存储被回收之前,它会被调用(一次)。这是一个比评论中的声明更弱的声明。如果 JVM 在 GC 运行后很快退出,则可能无法最终确定垃圾收集对象的一种情况。
当类
finalize
方法永远不会返回 1 时,会出现另一种(病态)情况。当该类的一个实例被终结时,终结器线程将被卡住。当所有终结器线程都以这种方式卡住时,将无法终结更多可终结对象2。如果
Object::finalize
没有在类中被覆盖,JVM 将跳过该类的终结步骤。
1 - 这可能是由于无限循环,或者是因为 finalize()
方法卡在等待锁或等待从未发生的内部或外部“事件” .另请注意,在这种情况下,“从不”可能意味着“不会很长时间”。整体影响可能是一样的。
2 - 对象将无限期地位于终结队列中。这是内存泄漏。
关于java - 如果垃圾收集器在同一代码中两次保留内存,是否可以调用两次 finalize() 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61847749/