学习JVM之垃圾收集05——根节点枚举、安全点和安全区域(HotSpot)

学习JVM之垃圾收集05——根节点枚举、安全点和安全区域(HotSpot),第1张

学习JVM之垃圾收集05——根节点枚举、安全点和安全区域(HotSpot)

目录

根节点枚举

什么是根节点枚举?

是怎样进行的

安全点

选取

线程中断

主动式

抢先式(几乎不用)

安全区域

什么是安全区域?

具体怎么解决问题


根节点枚举 什么是根节点枚举?

        根据可达性分析的方法去判断对象生死的话,我们需要找到各个起点。这个寻找的过程就叫做根节点枚举。

是怎样进行的

        到目前为止,所有垃圾收集器的根节点枚举 *** 作都必须暂停用户线程。也就是说会面临和内存碎片整理类似的 “Stop The World” 。

        虚拟机有办法直接得到哪些地方存在着对象引用。在HotSpot中,是通过一组叫做OopMap的数据结构实现的。这里会记录下关于引用的信息。

安全点

OopMap会在特定的位置做信息记录,这些位置就叫做安全点。

安全点的出现呢,也让线程的停止有了合适的时间,程序执行时,要执行到安全点的位置上方可停止。

选取

如果安全点很多,那OopMap就会很大,内存开销变大。

安全点很少,那垃圾收集器的等待时间就会很长。

安全点的选取需要一个标准:具有方法调用、循环跳转、异常跳转等,指令序列复用功能的指令才会产生安全点。

为什么呢?

        安全点位置的选取基本上是以“是否具有让程序长时间执行的特征”为标准 进行选定的,因为每条指令执行的时间都非常短暂,程序不太可能因为指令流长度太长这样的原因而长时间执行“长时间执行”的最明显特征就是指令序列的复用,例如方法调用、循环跳转、异常跳转 等都属于指令序列复用,所以只有具有这些功能的指令才会产生安全点。

线程中断

这里所谓的线程中断,是说实现让线程跑到最近的安全点再停止。有两种方法可以实现

主动式中断、抢先式中断

主动式

在安全点的位置,设置一个 轮询标志位 ,当需要中断时,设置为真。

线程执行到安全点位置的指令时,会查看轮询标志位。如果是真,那么线程把自己挂起,实现中断。

除此之外,在需要分配内存的指令上也需要设置 轮询标志位 。保证垃圾收集在分配内存之前执行。 

抢先式(几乎不用)

这是一种几乎没人用的。

        在垃圾收集器提出中断时,停止所有线程,看哪个线程没有在安全点上,唤醒它。让其跑到安全点。

安全区域

        当线程处于没有运行的状态(比如Sleep状态或者Blocked状态)时,无法走到安全点挂起自己。安全区域就是来解决这个事情的。

什么是安全区域?

        指在一段程序代码内,没有引用的关系变化,即在这一区域任何地方中断线程都是安全的。

具体怎么解决问题

        线程在进入安全区域时,会标记自己在安全区域。此时虚拟机在垃圾收集时就不用管他们了。

        出去时会询问虚拟机是否已经完成根节点枚举(或垃圾收集过程中其他需要暂停用户线程的阶段)。若已完成,线程继续执行。如没有完成,程序停止,等待离开安全区的指令。

 

这一篇就到这里了。

早睡早起,注意身体。早起之王祝你一日千里

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5722461.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存