如果垃圾收集器在同一代码中两次保留内存,是否可以调用两次 finalize() 方法?
Can the finalize() method be called twice if the garbage collector retains memory twice in the same code?
我在很多地方都发现,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()
。
请注意,finalize()
在 Java 9 及更高版本中 已弃用 ,原因在 javadoc 中已说明。建议您改为使用以下其中一项:
AutoCloseable
+ 尝试使用资源
Cleaner
PhantomReference
有人这样评价:
finalize()
is called for every Object
that is collected.
由于几个原因,这不是真的。
javadoc 明确 声明不保证 finalize
会被调用。可以保证的是,在对象的存储被回收之前,它会被调用(一次)。这比评论中的陈述更弱。
如果 JVM 在 GC 运行.
后很快退出,则可能无法最终确定垃圾收集对象的一种情况。
当 classes finalize
方法从不 returns1 时,会出现另一种(病态)情况。当 class 的一个实例被终结时,终结器线程将被卡住。当所有终结器线程都以这种方式卡住时,将无法终结更多可终结对象2.
如果 Object::finalize
未在 class 中被覆盖,JVM 将跳过 class.
的最终化步骤
1 - 这可能是由于无限循环,或者是因为 finalize()
方法卡在等待锁定或等待从未发生的内部或外部“事件”。另请注意,在这种情况下,“从不”可能意味着“不会很长时间”。整体效果可以一样。
2 - 对象将无限期地位于终结队列中。这是内存泄漏。
我在很多地方都发现,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()
。
请注意,finalize()
在 Java 9 及更高版本中 已弃用 ,原因在 javadoc 中已说明。建议您改为使用以下其中一项:
AutoCloseable
+ 尝试使用资源Cleaner
PhantomReference
有人这样评价:
finalize()
is called for everyObject
that is collected.
由于几个原因,这不是真的。
javadoc 明确 声明不保证
finalize
会被调用。可以保证的是,在对象的存储被回收之前,它会被调用(一次)。这比评论中的陈述更弱。如果 JVM 在 GC 运行.
后很快退出,则可能无法最终确定垃圾收集对象的一种情况。当 classes
finalize
方法从不 returns1 时,会出现另一种(病态)情况。当 class 的一个实例被终结时,终结器线程将被卡住。当所有终结器线程都以这种方式卡住时,将无法终结更多可终结对象2.如果
的最终化步骤Object::finalize
未在 class 中被覆盖,JVM 将跳过 class.
1 - 这可能是由于无限循环,或者是因为 finalize()
方法卡在等待锁定或等待从未发生的内部或外部“事件”。另请注意,在这种情况下,“从不”可能意味着“不会很长时间”。整体效果可以一样。
2 - 对象将无限期地位于终结队列中。这是内存泄漏。