Roh*_*kar 3 java garbage-collection
我在很多地方发现,当垃圾收集器或 System.gc() 成功保留冗余对象消耗的内存而不再引用它时,会调用 java 中的 finalize() 方法。还发现这个方法调用不超过一次。我对 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();
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,finalize 方法被调用了两次,因为内存堆两次都符合垃圾清理的条件。所以,我有点困惑,我是否知道整件事是正确的,或者它是否应该按照它的行为方式行事。
finalize()不会。该方法只会被 GC 在一个对象上调用一次。JVM 在对象头(我认为)中设置了一个标志,表示它已经完成,并且不会再次完成它。
在javadoc中明确指出这一点:
“对于任何给定的对象,Java 虚拟机永远不会多次调用 finalize 方法。”
当然,没有什么可以阻止对象方法this.finalize()多次调用。
请注意,finalize()被弃用Java中9,后来在Javadoc中说明理由。建议您改用以下方法之一:
AutoCloseable + 尝试使用资源CleanerPhantomReference有人是这样评论的:
finalize()被收集的每一个都 被调用Object。
出于几个原因,情况并非如此。
javadoc明确声明不保证finalize会被调用。可以保证的是,它会在对象的存储被回收之前被调用(一次)。这是一个比评论所做的陈述更弱的陈述。
垃圾收集对象可能无法最终确定的一种情况是 JVM 在 GC 运行后不久退出。
当类finalize方法从不返回1时,会发生另一种(病态的)情况。当该类的实例完成时,终结器线程将卡住。当所有终结器线程都以这种方式卡住时,就无法终结更多可终结对象2。
如果Object::finalize未在类中覆盖,JVM 将跳过该类的终结步骤。
1 - 这可能是由于无限循环,或者因为该finalize()方法卡在等待锁定或等待从未发生的内部或外部“事件”。还要注意,在这种情况下,“从不”可能意味着“很长时间没有”。整体影响可能相同。
2 - 对象将无限期地位于终结队列中。这是内存泄漏。