如果我们覆盖 finalize 方法,为什么可以增加分配阶段?
我听说在 Joshua Bloch 写的书中,如果我们重写 finalize 方法,分配和内存收集可能会增加到 430 次.
I have heard that in Joshua Bloch book written that allocation and memory collection might be increased to 430 times if we override finalize method.
对我来说很明显,内存收集可能会更慢,因为 gc 需要额外的迭代来释放内存.
It is clear for me that memory collection can work slower because additional iteration requred for gc to free memory.
但是为什么分配阶段可以增加呢?
But why allocation phase can be increased?
推荐答案
我已经搜索了原文:
在我的机器上,创建和销毁一个简单对象的时间大约是5.6 纳秒.添加终结器会将时间增加到 2,400 ns.换句话说,它是关于使用终结器创建和销毁对象的速度要慢 430 倍.
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.
因此,这不是一般性陈述,而只是一份证据报告,表明其背后存在模式,而不是数字是可重现的.当使用不那么微不足道的对象或更多的对象时,这个因素可能会发生变化.
So this isn’t a general statement, but just a report of evidence that suggests that there is a pattern behind it, not that the number is reproducible. This factor is likely to change when using not-so-trivial objects or just a lot more of them.
当然,这些成本取决于最终确定的实际实施方式.在 HotSpot 中,Finalizer
将通过调用 Finalizer.register
方法每次使用一个不平凡的对象finalize()
方法被创建.
Of course, these costs depend on how finalization is actually implemented. In HotSpot, an instance of Finalizer
will be created by calling the Finalizer.register
method every time an object with a non-trivial finalize()
method is created.
这可能意味着比仅分配两个对象而不是一个对象的成本要高得多.这些 Finalizer
实例将被强链接,这对于防止 Finalizer
实例本身的集合是必要的,并且它们具有对构造对象的引用.换句话说,无论最初分配的对象是多么局部,新对象都会逃逸,从而阻碍后续的许多优化.
This might imply much more costs than just allocating two objects instead of one. These Finalizer
instances will be strongly linked, which is necessary to prevent the collection of the Finalizer
instances themselves, and they have a reference to the constructed object. In other words, regardless of how local the object allocation initially was, the new object will escape, hindering lots of subsequent optimizations.
当谈到破坏"时,回收一个普通的对象是一个空操作.不会采取任何行动,事实上,不可能对无法访问的对象执行任何操作,因为它是无法访问的.特殊的可达性状态只能通过有一个可达的 Reference
对象来遇到,比如上面提到的 Finalizer
对象,它持有对特定对象的引用(而对象不是通过任何其他普通引用遇到.然后,Reference
对象可以入队,之后(一个)终结器线程可以采取适当的行动.
When it comes to "destruction", reclaiming an ordinary object is a no-op. No action will be taken and, in fact, it is impossible to do anything with the unreachable object, as it is unreachable. Special reachability states can only be encountered by having a reachable Reference
object, like the Finalizer
object mentioned above, which holds a reference to the particular object (while the object wasn’t encountered through any other ordinary reference. Then, the Reference
object can be enqueued, after which (one of) the finalizer thread(s) can take the appropriate action.
当然,将不采取行动"与任何其他行动进行比较可能会导致任意因素.绝对值是 2,400ns,这对于涉及将对象入队并通知另一个线程轮询队列的操作是合理的.
Of course, comparing "no action" with any other action can lead to arbitrary factors. The absolute number was 2,400ns, which is reasonable for an action that involves enqueuing an object and notifying another thread to poll the queue.
相关文章