5

从有效的Java:

哦,还有一件事:使用终结器会导致严重的性能损失。在我的机器上,创建和销毁一个简单对象的时间约为 5.6 ns。添加终结器会将时间增加到 2,400 ns。换句话说,使用终结器创建和销毁对象的速度大约慢了 430 倍。

是什么让 Finalizers 如此昂贵?

4

3 回答 3

5

关键的区别在于终结器方法的存在,无论它做什么。一旦 GC 有了可终结的对象,它就必须更加努力地完成所有的内务处理。它必须将它们标记为可终结,将它们保存在池中,运行终结,检查它们之后是否复活,处理各种多线程问题和终结代码,等等。

这种差异在 GC 的年轻代中表现得最为明显:在一个乐观且并非完全罕见的情况下,GC'ing 归结为一个操作:递减指向第一个可用内存地址的指针。使用终结器,就是上面概述的整个过程。

于 2012-07-17T14:09:53.660 回答
5

http://www.ibm.com/developerworks/java/library/j-jtp01274/index.html

从上面的链接中提取

与没有终结器的对象相比,具有终结器的对象(具有非平凡 finalize() 方法的对象)具有显着的开销,应谨慎使用。可终结的对象分配和收集都比较慢。在分配时,JVM 必须向垃圾收集器注册任何可终结对象,并且(至少在 HotSpot JVM 实现中)可终结对象必须遵循比大多数其他对象更慢的分配路径。同样,可终结对象的收集速度也较慢。至少需要两个垃圾收集周期(在最好的情况下)才能回收可终结对象,并且垃圾收集器必须做额外的工作来调用终结器。结果是分配和收集对象花费了更多时间,垃圾收集器承受了更大的压力,因为不可访问的可终结对象使用的内存保留的时间更长。再加上终结器不能保证在任何可预测的时间范围内运行,甚至根本不能保证这一事实,您可以看到在相对较少的情况下终结器是正确的工具。

于 2012-07-17T14:11:46.310 回答
0

当您进行基准测试时,您可能会对对象的使用寿命进行基准测试。

对象存在超出其使用寿命,基本上在最后一个程序引用消失和垃圾收集例程(在不同的线程中运行)检测到分离的对象之间存在时间延迟。添加终结器时,对象的“使用寿命”现在会延长,直到垃圾收集检测到分离的对象之后,并且在 JVM 运行终结方法之后。

这不是 100% ,因为存在终结方法,终结方法增加了很多时间,其中很多时间都在等待垃圾收集线程唤醒并最终偶然发现您的分离对象(并决定对其进行处理)。

于 2012-07-17T14:16:34.687 回答