目录
根节点枚举
什么是根节点枚举?
是怎样进行的
安全点
选取
线程中断
主动式
抢先式(几乎不用)
安全区域
什么是安全区域?
具体怎么解决问题
根节点枚举 什么是根节点枚举?
根据可达性分析的方法去判断对象生死的话,我们需要找到各个起点。这个寻找的过程就叫做根节点枚举。
是怎样进行的
到目前为止,所有垃圾收集器的根节点枚举操作都必须暂停用户线程。也就是说会面临和内存碎片整理类似的 “Stop The World” 。
虚拟机有办法直接得到哪些地方存在着对象引用。在HotSpot中,是通过一组叫做OopMap的数据结构实现的。这里会记录下关于引用的信息。
安全点
OopMap会在特定的位置做信息记录,这些位置就叫做安全点。
安全点的出现呢,也让线程的停止有了合适的时间,程序执行时,要执行到安全点的位置上方可停止。
选取
如果安全点很多,那OopMap就会很大,内存开销变大。
安全点很少,那垃圾收集器的等待时间就会很长。
安全点的选取需要一个标准:具有方法调用、循环跳转、异常跳转等,指令序列复用功能的指令才会产生安全点。
为什么呢?
安全点位置的选取基本上是以“是否具有让程序长时间执行的特征”为标准 进行选定的,因为每条指令执行的时间都非常短暂,程序不太可能因为指令流长度太长这样的原因而长时间执行“长时间执行”的最明显特征就是指令序列的复用,例如方法调用、循环跳转、异常跳转 等都属于指令序列复用,所以只有具有这些功能的指令才会产生安全点。
线程中断
这里所谓的线程中断,是说实现让线程跑到最近的安全点再停止。有两种方法可以实现
主动式中断、抢先式中断
主动式
在安全点的位置,设置一个 轮询标志位 ,当需要中断时,设置为真。
线程执行到安全点位置的指令时,会查看轮询标志位。如果是真,那么线程把自己挂起,实现中断。
除此之外,在需要分配内存的指令上也需要设置 轮询标志位 。保证垃圾收集在分配内存之前执行。
抢先式(几乎不用)
这是一种几乎没人用的。
在垃圾收集器提出中断时,停止所有线程,看哪个线程没有在安全点上,唤醒它。让其跑到安全点。
安全区域
当线程处于没有运行的状态(比如Sleep状态或者Blocked状态)时,无法走到安全点挂起自己。安全区域就是来解决这个事情的。
什么是安全区域?
指在一段程序代码内,没有引用的关系变化,即在这一区域任何地方中断线程都是安全的。
具体怎么解决问题
线程在进入安全区域时,会标记自己在安全区域。此时虚拟机在垃圾收集时就不用管他们了。
出去时会询问虚拟机是否已经完成根节点枚举(或垃圾收集过程中其他需要暂停用户线程的阶段)。若已完成,线程继续执行。如没有完成,程序停止,等待离开安全区的指令。
这一篇就到这里了。
早睡早起,注意身体。早起之王祝你一日千里