可终结对象在回收之前至少需要2个垃圾回收周期?

Lav*_*ari 2 java garbage-collection finalize

我正在阅读这篇文章,我无法真正理解最终化对象(覆盖该finalize方法的对象)在回收之前至少需要2个GC周期.

在可回收可完成对象之前,它至少需要两次垃圾收集周期(在最好的情况下).

有人还可以详细解释一个可终结的对象如何可以采用多个GC循环进行回收?

我的逻辑论点是,当我们覆盖finalize方法时,运行时必须使用垃圾收集器注册此对象(以便GC可以调用finalize此对象,这使我认为GC将引用所有可终结的对象).为此,GC必须对可终结对象保持强有力的参考.如果是这种情况,那么该对象如何成为GC首先进行回收的候选对象?我通过这个理论达成了矛盾.

PS:我知道覆盖finalize不是推荐的方法,并且自Java 9以来不推荐使用此方法.

Hol*_*ger 5

你是对的,垃圾收集器需要引用可终结的对象.当然,在确定对象在完成之前是否仍可达时,不得考虑此特定引用.这意味着有关垃圾收集器引用性质的特殊知识.

当垃圾收集器确定某个对象有资格进行最终化时,终结器将运行,这意味着该对象再次变得强烈可达,至少只要执行终结器即可.在最终确定之后,对象必须再次无法访问,并且必须在可以回收对象的内存之前检测到该对象.这就是为什么它需要至少两个垃圾收集周期.

在广泛使用的Hotspot/OpenJDK环境(也可能在IBM的JVM中)的情况下,这是通过创建一个特殊的非公共子类a的实例来实现ReferenceFinalizer,当一个对象时,它的类具有非平凡性finalize()方法,已创建.与弱引用和软引用一样,当没有对引用的强引用存在时,这些引用会被垃圾收集器排队,但它们不会被清除,因此终结器线程可以读取该对象,使其再次强制可用于完成.此时,它Finalizer被清除,但也没有被引用,所以无论如何它都会像普通对象一样被收集,所以在下一次指示对象变得无法访问时,不再存在对它的特殊引用.

对于其类具有"平凡终结器"的对象,即finalize()由其继承的方法java.lang.Object或空finalize()方法,JVM将采用快捷方式而不是首先创建Finalizer实例,所以你可以说,这些对象是大多数所有对象,从一开始就表现得好像它们的终结器已经运行一样.

  • 因为没有保证垃圾收集周期识别特定的无法访问的对象.任何一般性陈述都必须小心,不要保证不保证的东西.实际上,当终结器仍在运行时,第二个(以及第三个和第四个......)垃圾收集周期可能会发生,因此,对象仍然可以访问.实际上,第二个循环甚至可能在对象仍然排队并且最终化尚未开始时发生.支持最大暂停时间的垃圾收集器可能无法在一个周期中识别所有无法访问的对象. (2认同)