谈谈Java GC的可达性分析

Java面试 潘老师 9个月前 (09-05) 178 ℃ (0) 扫码查看

Java面试题:谈谈Java GC的可达性分析

得分点:

  • GC Roots
  • 引用链

标准回答:

内存管理子系统通常使用可达性分析算法来判定对象是否存活。这个算法的核心思想是从一组称为“GC Roots”的根对象开始,通过引用关系向下搜索对象,搜索过程中所经过的路径被称为“引用链”。如果某个对象到GC Roots之间没有任何引用链,或者用图论的术语来说,无法从GC Roots到达该对象,那么这个对象就被认为是不可达的,即不可能再被使用,可以被回收。

在Java技术体系中,可以作为GC Roots的对象包括以下几种:

  • 在虚拟机栈中引用的对象,例如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。
  • 在方法区中类静态属性引用的对象,例如Java类的引用类型静态变量。
  • 在方法区中常量引用的对象,例如字符串常量池中的引用。
  • 在本地方法栈中引用的对象。
  • JVM内部的引用,如基本数据类型对应的Class对象、常驻的异常对象以及系统类加载器。
  • 所有被同步锁持有的对象。
  • 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

加分回答:

要真正宣告一个对象死亡,通常需要经历两次标记过程:

第一次标记:

在可达性分析后,如果发现对象没有与GC Roots相连接的引用链,对象将被第一次标记。然后进行一次筛选,检查对象是否需要执行finalize()方法。如果对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,那么虚拟机将视为对象“没有必要执行finalize()”。反之,将对象放入名为F-Queue的队列中,并稍后由虚拟机的Finalizer线程执行其finalize()方法。

第二次标记:

稍后,收集器将对F-Queue中的对象进行第二次小规模的标记。如果对象在finalize()方法中成功拯救自己,只需重新与引用链上的任何一个对象建立关联,例如将自己(this)赋值给某个类变量或对象的成员变量,那么在第二次标记时,对象将被移出“即将回收”的集合。如果对象无法逃脱,它将被回收。

finalize()方法是对象逃脱死亡命运的最后机会。需要注意的是,每个对象的finalize()方法只会被系统自动调用一次。此外,finalize()方法的运行代价高昂,不确定性较大,无法保证各个对象的调用顺序。因此,finalize()方法已被官方明确声明为不推荐使用的语法。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/javainterview/8707.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】