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

why allocation phase can be increased if we override finalize method?

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

我很清楚内存收集的速度可能会变慢,因为 gc 需要额外的迭代来释放内存。

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

我搜索了原文:

On my machine, the time to create and destroy a simple object is about 5.6 ns. Adding a finalizer increases the time to 2,400 ns. In other words, it is about 430 times slower to create and destroy objects with finalizers.

所以这不是一个笼统的陈述,而只是一份证据报告,表明其背后存在某种模式,而不是该数字是可重复的。当使用不那么平凡的对象或使用更多对象时,这个因素可能会改变。

当然,这些成本取决于最终确定的实际实施方式。在 HotSpot 中,每次创建具有非平凡 finalize() 方法的对象时,都会有一个 Finalizer will be created by calling the Finalizer.register 方法的实例。

这可能比仅分配两个对象而不是一个对象意味着更多的成本。这些 Finalizer 个实例将被强链接,这是防止收集 Finalizer 个实例本身所必需的,并且它们具有对构造对象的引用。换句话说,无论对象分配最初有多局部,新对象都会逃逸,阻碍大量后续优化。

当谈到“销毁”时,回收一个普通对象是一个空操作。不会执行任何操作,事实上,无法对无法访问的对象执行任何操作,因为它 unreachable。特殊的可达性状态只能通过拥有一个可达的 Reference 对象来遇到,比如上面提到的 Finalizer 对象,它持有对特定对象的引用(而该对象不是通过任何其他普通引用遇到的. 然后,可以将 Reference 对象入队,之后(其中一个)终结器线程可以采取适当的操作。

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