对象什么时候会被GC

2019-08-22  本文已影响0人  风吹过那天

前言

在堆中几乎存放着所有的对象实例,垃圾收集器在对堆进行回收前,要判断哪些对象是“活着”的,哪些不可能再被任何途径所使用。首先介绍两种判读对象是否活着的算法。

引用计数法

可达性分析算法

由上图可知通过GC Roots对象1,2,3,4均是可达的,而对象5,6,7通过GC Roots是不可达的,所以它们会被判定为可回收对象。


生存还是死亡

一个对象真正的死亡需要经历两次标记过程,若对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它会被第一标记且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法,当对象没有覆盖finalize()方法,或该方法已经被虚拟机调用过,虚拟机将这两种情况视为“没有必要执行”。这类对象会被放置在yigeF-Queue队列中,由一个低优先级的线程去执行。稍后GC将对F-Queue中的对象进行第二次小规模的标记,若对象在finalize()方法中重新与引用链上的任意对象建立了关联,那在第二次标记时它将被移除出“即将回收的集合”,否则会被回收。


垃圾回收算法

HopSpot算法实现

采用的是准确式GC,虚拟机可以知道哪些地方存着对象引用。采用一组称为OopMap的数据结构来达到这个目的。在类加载完成的时候,HotSpot就把对象内什么偏移量上什么类型的数据计算出来,在JIT编译过程中,也会在特定的位置记录下栈和寄存器中哪些位置是引用。

安全点:前面提到的在“特定的位置”记录这些信息,这些位置称为安全点(Safepoint),即程序执行时并非在所有地方都能停顿下来GC,只有到达安全点时才能暂停。

安全点的选定是以程序“是否有让程序长时间执行的特征”为标准进行选定的。对于Safepoint而言另一个问题是如何在GC发生时,所有线程都能跑到最近的安全点再停下来。有两种方案可以选择,分别是抢先式中断和主动式中断

安全区:是指在一段代码片段之中,引用关系不会发生变化,这个区域中的任意地方开始GC都是安全的。可以把Safe Region看作是被扩展了的安全点。主要是解决了当线程处于Sleep或者Blocked状态时,线程无法响应JVM中断请求,“走”到安全的地方去挂起的问题。

上一篇 下一篇

猜你喜欢

热点阅读