Java垃圾回收机制-可达性分析算法

基本思路

通过一系列的‘’GC Roots‘’对象作为起点进行搜索,如果在‘’GC Roots‘’和对象之间没有可达的路径(引用链),则称该对象是不可达的,被判定不可达的对象不一定会成为可回收对象。被判定不可达的对象至少要经历两次标记过程,如果在这两次标记过程中扔没有逃脱成为可回收对象的可能性,则基本就成为可回收的对象了。在这里插入图片描述
对象ObjectC、ObjectE、ObjectF到GC Roots 是不可达的,因此他们会判定为可回收对象。

GC Roots 对象

  1. 虚拟机栈(栈帧中的本地变量)中引用的对象。虚拟机栈中的引用的对象,我们在程序中正常创建一个对象会在堆上开辟一块空间,同时会将这块空间的地址作为引用保存在虚拟机的栈中,如果对象的生命周期结束了,那么引用就回从虚拟机栈中出栈,因此如果在虚拟机占中存在引用,就说明这个对象还在被使用。
  2. 方法区中类静态属性引用的对象。由于在虚拟机栈是线程私有的,全局静态对象会保存在方法区中。
  3. 方法区中常量引用的对象。final关键字修饰
  4. 本地方法栈中(Native方法)引用的对象。Java调用C++或C代码,会使用native方法,JVM中会有一块本地方法栈,用于保存这些对象的引用。

两次标记流程

即使在可达性分析算法中对象到GC Roots 的应用链不可达,也并非是”非死不可“,这些对象暂时处于”缓刑“阶段,要真正的宣告一个对象死亡,至少要要经历再次标记过程。

  1. 第一次标记并进行筛选。条件:此对象是否有必要执行finalize()方法,当对象没有覆盖finalize()方法,或者finalize()方法被虚拟机调用过,虚拟机将这两种情况都视为”没有必要执行“,对象被虚拟机回收。
  2. 第二次标记。如果该对象被判定为有必要执行finalize()方法,那么这个对象会被放置到一个名为F-Queue的队列中,并在稍后由虚拟机自行建立的优先级比较低的线程Finalizer去执行。这里的‘执行’是虚拟机会触发finalize()方法。finalize()方法是对象逃离死亡的最后一次自救,稍后GC将对F-Queue进行小规模的标记,如果对象重新与应用链上的对象建立联系,第二次标记会将他移除“即将回收”的集合。

虚拟机线程在执行finalize()方法不会等待该对象方法结束,这样的原因是如果对象的finalize()方法运行缓慢,或者发生死循环,将导致F-Queue队列中其他对象一直处于等待状态,有可能导致内存回收系统崩溃。

在这里插入图片描述
参考文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值