美文网首页
finalize 与 Java GC

finalize 与 Java GC

作者: 吃猫的老鼠 | 来源:发表于2015-05-27 11:13 被阅读215次

闲逛ITEye时看到了译帝的一篇翻译博客,其中提到了关于Java类重写finalize方法后带来的诡异的GC overhead limit问题。博客的结尾非常详细的说明了这个问题产生的原理,但是始终有一个地方没有得到清晰的答案:由于finalize方法是Object类的protected方法,即无论重写与否,所有的Java类都会带有finalize方法,但为什么只有重写之后才会出现GC问题,不重写与重写的真实差别到底在哪儿?

通过思考始终得不到答案,索性打开Eclipse直接调试代码:

首先验证了博客中的现象的确可以重现。

中间一度怀疑问题的原因可能是finalize方法中引用了类的静态变量AtomicInteger会引起GC的问题(实际上这个方向是错误的,GC是根据对象是否存在被引用关系来判断对象是否回收,惭愧),删掉原来的方法体然后随意在finalize方法中声明了一个变量,结果运行时问题仍然存在。

到了此时,开始怀疑是不是和finalize方法体有关系了,直接删除掉finalize方法体中的所有内容,运行后发现问题真的不存在了!

由于出现GC问题时内存堆中存在大量Finalizer对象,而Finalizer对象只能通过Finalizer类的静态register方法创建,因此尝试在register方法中加上断点对两种情况分别运行,发现方法体为空时,register方法不会被调用,这样自定义对象便没有被任何对象引用,可以轻松的被GC回收掉。

由于register方法是被VM所调用,只能求助于莫枢大神,而莫枢也确认了只要Java类以及它所有的祖先类中不含有finalize方法或者finalize方法体为空时,VM便不会将该类的对象实例注册为finalizable对象(地址)。

至此,算是把整个问题的来龙去脉给整理的差不多了:

JVM创建自定义对象。

JVM检测对象类以及祖先类是否含有非空的finalize方法定义,如果均没有,则不进行后续的Finalizer相关处理。

JVM调用Finalizer类的静态register方法,创建包含该对象引用的Finalizer对象,同时Finalizer静态类将该Finalizer对象加入到一个单向链表中。

运行过程中,JVM会将这些Finalizer对象的状态更新为pending(这部分可以参考java.lang.ref.Reference类中的说明)。

Reference类中的ReferenceHandler线程会扫描到这些状态为pending的Finalizer对象,将这些对象enqueue到Finalizer静态类引用的ReferenceQueue(非Finalizer中的单向链表)当中。

Finalizer线程从ReferenceQueue中逐一弹出Finalizer对象,首先将Finalizer对象从Finalizer的单向链表中删除,解除了Finalizer静态类对Finalizer对象的引用关系,之后调用Finalizer对象引用的自定义对象的finalize方法,Finalizer对象以及自定义对象此时均可被GC回收。

由于Finalizer线程的低优先级,可能引起旧对象的释放速度无法跟上新对象的创建速度,引起OutOfMemory问题(例子中的GC overhead limit原因是由于新对象创建的代价太低而旧对象回收的代价较高导致CPU用于GC回收的时间比例超过98%)

最后,网易研究院的马进在他的博客中非常详细的阐述了finalize的原理以及因此引发的案例,也非常值得一读。

相关文章

  • finalize 与 Java GC

    闲逛ITEye时看到了译帝的一篇翻译博客,其中提到了关于Java类重写finalize方法后带来的诡异的GC ov...

  • (转)Java面试重难点剖析(部分)

    1、高并发访问数据库优化方法 2、java finalize方法总结、GC执行finalize的过程 3、简单理解...

  • Finalize 与 GC

    预备知识 Java的Gc只负责内存的清理,其它方面的清理要程序员手工操作 调用Gc并不能保证Gc一定会执行,因为G...

  • Java面试重难点剖析(不断更新)

    Java面试重难点剖析(不断更新) 1、高并发访问数据库优化方法 2、 java finalize方法总结、GC执...

  • 2020-07-21 Finalize和Dispose

    Finalize和Dispose都是用来释放资源的。 Finalize也就是析构函数,是由gc来决定的,等到gc执...

  • finalize方法相关

    finalize原理简述 当一个对象变成(GC Roots)不可达时,GC会判断对象是否覆盖了finalize方法...

  • java finalize方法总结、GC执行finalize的过

    注:本文的目的并不是鼓励使用finalize方法,而是大致理清其作用、问题以及GC执行finalize的过程。 1...

  • gc&finalize()

    gc:垃圾回收finalize():是类似于析构函数的东西,如果覆写了该方法,则在垃圾回收过程中会调用该方法,然后...

  • GC垃圾回收机制

    GC算法 垃圾收集器 (标记-清除,复制,压缩,gc垃圾收集需要判断是否覆盖finalize方法?) 概述 垃圾收...

  • finalize方法

    finalize方法/Finalize_.java 1.当对象被回收时,系统自动调用该对象的finalize方法。...

网友评论

      本文标题:finalize 与 Java GC

      本文链接:https://www.haomeiwen.com/subject/rourqttx.html