哪种参考终结器(FinalReference)或弱/幻影/软参考具有更高的GC优先级

时间:2019-10-03 19:24:46

标签: java reference garbage-collection jvm g1gc

在创建具有非平凡finalize()方法的对象时,JVM将创建以该对象为对象的FinalizerFinalReference)。如果该对象也被“软/弱”或“幻影引用”包装,将会发生什么? GC是否会首先尝试使Finalizer(调用finalize方法)入队,然后使另一个Reference或相反的对象入队?

1 个答案:

答案 0 :(得分:2)

我认为,您的问题实际上与排队时间无关。

考虑the package documentation

通知部分
  

在垃圾回收器确定引用对象的可到达性已更改为与引用类型相对应的值之后的一段时间,它将引用添加到关联的队列中。

(请注意“之后的某个时间”)

同样,所有引用类型都具有以下形式的语句:

  

假设垃圾收集器在某个时间点确定对象是弱可到达的。到那时,它将自动清除对该对象的所有弱引用,以及对所有其他弱可达对象的弱引用,这些对象都可以通过一系列强引用和软引用从该对象到达。同时,它将声明所有以前难以到达的对象都是可终结的。同时或在以后的某个时间,它将把那些新近清除的弱引用加入队列,该弱引用已在引用队列中注册。

(摘自WeakReference;请注意“同时或以后”)

在实践中,垃圾收集器将发现的引用移交给另一个线程进行异步排队。由于未指定的延迟使应用程序从队列中检索引用的顺序不确定,因此在这里询问顺序毫无意义。

但是,我想您实际上对另一个“ 特定时间点”感兴趣,当“ 垃圾收集器确定引用对象的可到达性已更改为值对应于引用的类型”,并将决定自动清除引用并使其符合入队条件。

当混合使用多个不同类型的引用对象(包括Finalizer引用但没有强引用)时,存在两种可能的情况:

  1. 至少有一个软基准,并且没有存储压力。然后,垃圾收集器可能决定不清除响应。排队加入任何参考。
  2. 没有软引用,或者垃圾回收器确定内存压力证明清除软引用是合理的。然后清除所有 软弱引用,并将所有软弱引用和终结器引用移入队列。
    只有幻像引用保持不变。

请注意,一旦完成最终确定,就不再存在Finalizer引用,但是在最终确定期间,可能会创建新的软或弱引用。因此,所产生的场景与具有简单finalize()方法的对象的优化处理相同。没有Finalizer引用,可以混合使用软引用,弱引用和幻像引用。当没有足够的参考依据时,我们又有两种可能的情况:

  1. 至少有一个软基准,并且没有存储压力。然后,垃圾收集器可能决定不清除响应。排队加入任何参考。
  2. 没有软引用,或者垃圾回收器确定内存压力证明清除软引用是合理的。然后,清除所有软,弱和幻像引用 A ,并移交所有软,弱和幻像引用以排队。

A 幻像引用在Java 9或更高版本中已清除。在以前的版本中,它们仅在未清除的情况下入队。