java - 为什么如果我们重写 Finalize 方法可以增加分配阶段?

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

我听说 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 中, Finalizer 的实例将通过调用 Finalizer.register 创建每次创建具有重要 finalize() 方法的对象时都会调用该方法。

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

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

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

关于java - 为什么如果我们重写 Finalize 方法可以增加分配阶段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41378606/

相关文章:

arrays - 垃圾收集器是否保留仅由原始指针引用的数组?

java - 在垃圾收集器启动之前,如何回收不再需要的对象?

java - 线程是否可以先通过安全发布获取对象,然后不安全地发布它?

java - 设置 HashMap 线程安全吗?

java - 如何找到自上次使用 JVM 进行垃圾回收以来耗时?

java - 通过未修改的原子引用的突变是否可见?

使用 DatatypeConverter 时,Java 字节数组不会转换回其原始字符串

java - 两个Fragment之间的接口(interface)通信

java - BouncycaSTLe Java - 从 TimestampToken 生成 tst 文件

java - TIFF 5.0 风格的 LZW 压缩有什么特别之处