可终结对象如何至少需要 2 个垃圾回收周期才能被回收?
我正在阅读 这篇 文章,我可以' 不太了解可终结对象(覆盖 finalize
方法的对象)如何至少需要 2 个 GC 周期才能被回收.
I'm reading this article and I can't really understand how the finalizable objects (objects which override the finalize
method) takes at least 2 GC cycles before it can be reclaimed.
至少需要两个垃圾回收周期(在最佳情况下)才能回收可终结对象.
It takes at least two garbage collection cycles (in the best case) before a finalizeable object can be reclaimed.
谁能详细解释一下一个可终结的对象怎么可能需要一个以上的 GC 周期来回收?
我的逻辑论点是,当我们覆盖 finalize 方法时,运行时将不得不向垃圾收集器注册这个对象(以便 GC 可以调用这个对象的 finalize
,这让我认为GC 将引用所有可终结的对象).为此,GC 必须保持对可终结对象的强引用.如果是这样的话,那么这个对象是如何成为 GC 回收的候选对象的呢?我通过这个理论得出了一个矛盾.
My logical argument is that when we override finalize method, the runtime will have to register this object with the garbage-collector (so that GC can call finalize
of this object, which makes me think that GC will have reference to all the finalizable objects). And for this, GC will have to keep a strong reference to the finalizable object. If that is the case then how this object became a candidate for reclamation by GC in the first place? I reach a contradiction by this theory.
PS:我知道重写 finalize
不是推荐的方法,并且自 Java 9 起该方法已被弃用.
PS: I understand that overriding finalize
is not the recommended approach and this method is deprecated since Java 9.
推荐答案
你说得对,垃圾收集器需要对可终结对象的引用.当然,在确定对象在最终确定之前是否仍然可达时,一定不能考虑这个特定的引用.这意味着对垃圾收集器的这种引用的性质有特殊的了解.
You are right in that the garbage collector needs a reference to finalizable objects. Of course, this particular reference must not be considered when deciding whether the object is still reachable before the finalization. This implies special knowledge about the nature of this reference to the garbage collector.
当垃圾收集器确定一个对象有资格进行终结时,终结器将运行,这意味着该对象再次变得强可达,至少只要终结器被执行.完成后,对象必须再次变得无法访问,并且必须检测到这一点,然后才能回收对象的内存.这就是为什么它至少需要两个垃圾回收周期.
When the garbage collector determines that an object is eligible for finalization, the finalizer will run, which implies that the object becomes strongly reachable again, at least as long as the finalizer is executed. After its finalization, the object must become unreachable again and this must be detected, before the object’s memory can be reclaimed. That’s why it takes at least two garbage collection cycles.
在广泛使用的 Hotspot/OpenJDK 环境(也可能在 IBM 的 JVM 中)的情况下,这是通过创建 参考
,一个Finalizer
,就在创建一个对象的时候,该对象的类具有非平凡的 finalize()
方法.像弱 &软引用,当不存在对所指对象的强引用时,这些引用被垃圾收集器排入队列,但它们没有被清除,因此终结器线程可以读取对象,使其再次强可达以进行终结.此时,Finalizer
被清除,但也不再被引用,所以无论如何它都会像普通对象一样被收集,所以下次引用对象变得不可访问时,不再存在对它的特殊引用.
In case of the widely used Hotspot/OpenJDK environment (and likely also in IBM’s JVM), this is implemented by creating an instance of a special, non-public subclass of Reference
, a Finalizer
, right when an object, whose class has a non-trivial finalize()
method, is created. Like with weak & soft references, these references are enqueued by the garbage collector when no strong reference to the referent exist, but they are not cleared, so the finalizer thread can read the object, making it strongly reachable again for the finalization. At this point, the Finalizer
is cleared, but also not referenced anymore, so it would get collected like an ordinary object anyway, so by the next time the referent becomes unreachable, no special reference to it exists anymore.
对于其类具有普通终结器"的对象,即 java.lang.Object
继承的 finalize()
方法或空的 finalize()
方法,JVM 将采取捷径,而不是首先创建 Finalizer
实例,所以你可以说,这些构成所有对象的大多数的对象,表现为如果他们的终结器已经运行,从一开始就运行.
For objects whose class has a "trivial finalizer", i.e. the finalize()
method inherited by java.lang.Object
or an empty finalize()
method, the JVM will take a short-cut and not create the Finalizer
instance in the first place, so you could say, these objects, which make the majority of all objects, behave as if their finalizer did already run, right from the start.
相关文章