如果我们覆盖finalize方法,为什么可以增加分配阶段?

时间:2016-12-29 11:15:11

标签: java garbage-collection java-memory-model finalization

我听说在Joshua Bloch的书中写道,如果我们覆盖finalize方法,分配和内存收集可能会增加到430倍。

对我来说很明显,内存收集可以更慢地工作,因为gc需要额外的迭代来释放内存。

但为什么分配阶段可以增加?

1 个答案:

答案 0 :(得分:1)

我搜索了原始声明:

  

在我的机器上,创建和销毁一个简单对象的时间是关于的   5.6 ns。添加终结器可将时间增加到2,400 ns。换句话说,它是关于   使用终结器创建和销毁对象的速度要慢430倍。

因此,这不是一般性陈述,而只是一份证据报告,表明其背后有一种模式,而不是该数字是可重复的。当使用不那么重要的对象或只使用更多的对象时,这个因素可能会改变。

当然,这些成本取决于如何实际完成最终确定。在HotSpot中,每次创建具有非平凡finalize()方法的对象时,都会通过调用Finalizer方法创建Finalizer.register的实例。

这可能意味着比分配两个对象而不是一个对象要多得多。这些Finalizer实例将强烈链接,这对于阻止Finalizer实例本身的收集是必要的,并且它们具有对构造对象的引用。换句话说,无论最初对象分配的本地化程度如何,新对象都将转义,阻碍了大量后续优化。

当涉及到“破坏”时,回收普通物体是无操作。不会采取任何操作,事实上,无法对无法访问的对象执行任何操作,因为它无法访问。只有拥有可访问的Reference对象(如上面提到的Finalizer对象)才能遇到特殊的可达性状态,该对象包含对特定对象的引用(而对象未通过任何其他普通引用遇到)然后,Reference对象可以入队,之后(其中一个)终结器线程可以采取适当的行动。

当然,将“无动作”与任何其他动作进行比较可能会导致任意因素。绝对数量为2,400ns,这对于涉及将对象排队并通知另一个线程轮询队列的操作是合理的。