深入理解java虚拟机系列第三版读后小记:(八)jvm的常用术语解释

深入理解java虚拟机系列第三版读后小记:八-jvm的常用术语解释

前言

之前文章中曾介绍过读写屏障,安全点,安全区域等一些名词,为此读者感到疑惑,所以特写此文解释一下。

根节点枚举

GC Roots的对象类型是固定的,所以任何一个垃圾回收器遍历寻找GC roots 都是需要进行STW的,但即使这样,一个方法区的对象多如牛毛循环遍历的话也是需要花费巨额的资源。所以出现了oopmap这一数据结构,在类加载进来的时候,就已经通过偏移量计算出该对象是什么类型,这样收集器扫描的时候就可直接拿到所需信心,无需从方法区逐个遍历。

安全点

通过oopmap的协助,可以快速完成根节点枚举,但有个问题,可能导致引用关系的或者导致oopmap内容变化的指令很多,如果每条指令都生成oopmap,那成本会很高昂。
所以oopmap只会在特定位置生成,特定的位置就是安全点。有了安全点的设定,执行stw的时候,用户线程就会跑到最近的安全点再进行中断,所有用户线程都中断后,收集器就开始工作。
目前中断有两种:

抢先式中断

抢先式中断不需要用线程的执行代码进行配合,虚拟机会中断所有的用户线程,然后检查到未达到安全点的用户线程,便恢复其线程让其运行到安全点再中断。

主动式中断

主动式中断是收集器工作时,不主动中断线程,而是设置一个标志位,所有线程会主动轮询这个标志位,为true时就在最近的安全点主动挂起,轮询标志的地方和安全点是重合的。

安全区域

安全区域可以是看成是安全点的延伸。之所以存在安全区域的概念,是因为安全点虽然完美停顿了运行线程,但对于sleep或者block状态的线程就无能为力了,所以为了解决这种状况,就出现了安全区域的概念。
安全区域表名一段代码片段中,引用关系不会变化,即从该区域任何一个位置开始进行收集也不会出现问题。
用户线程进入安全区域,首先会标明自己进入安全区域,那jvm就不会管理这些进入安全区域的线程,如若这些线程要离开安全区域,会检查jvm是否完成了根节点枚举或者其他需要STW的操作,如若完成了,就正常离开,检测到没有完成,就继续在安全区域内等待。

记忆集和卡表

记忆集主要是针对跨代引用的时候,用来记录从非收集区指向收集区的抽象数据结构。收集器只要通过记忆集来判断某一块非收集区域是否有指向收集区域的指针即可,不需要了解跨代指针的全部细节,所以实现记忆集的粒度可以粗些来降低记忆集的存储成本。
实现记忆集的通常有三种方式:

  1. 字长精度,每个记录精确到一个机器字长
  2. 对象精度,每个记录精确到一个对象
  3. 卡精度,每个记录精确到一块内存区域。
    所谓的第三种卡精度实现记忆集的方式就称为卡表。
    卡表的数据结构有些类似于map,key为指向卡页的索引,value为卡页,卡页也是一块内存区域,里面存储者对象字段。卡页的大小一般为2的整数次幂,其内存结构如图
    在这里插入图片描述
    其工作思想是,如果卡页内存在一个或多个对象的跨代指针,就修改对应卡表中的值为1,这个过程称为元素变脏dirty。所以收集器扫描卡表的时候,只要扫描变脏的卡页就能得到需要加入gc roots 的对象。

写屏障

卡表元素何时变脏,不知是否有读者考虑过,答案是明显的,当出现其他分代区域的对象引用了本区域的对象时,就会变脏。但如何赋值呢,如何对象赋值的时候就变脏卡表,如果是解释执行的字节码,可以有时间充分接入,但往往是编译后的机器指令流,所以要借助机器码来解决。维护卡表就是通过写屏障来解决的。
所谓的写屏障类型与aop的环形通知,就是对引用类型赋值的前后都属于写屏障范围。所以通过写屏障,虚拟机就会为赋值操作生成额外指令,检查到对象变动,就及时变脏卡表。

三色标记法

用户可达性分析的时候辅助工具,可加快可达性的遍历。所谓三色标记就是将对象按是否被收集器访问过的条件标记成三种颜色
白色:代表收集器没有访问过对象,即初始的时候所有对象都白色的,收集器标记结束后仍然为白色的对象即为不可达,是要被回收的对象。
黑色: 黑色代表对象所有引用都被扫描过,是存活的,即可达。任何指向黑色的对象都无须在扫描一遍,而黑色是不会直接连上白色的对象,即黑色访问白色中间必须有灰色对象。
灰色:灰色代表对象被收集器访问过,但至少有一个引用没有被扫描到

如果不与用户线程并行,那没任何问题,与用户线程并行的话,就会产生两种问题:
1.即错标死亡对象为存活对象,这还可以接受,只是增加了浮游垃圾,活到下一轮垃圾回收器再被回收掉。
2. 即将存活对象错标成死亡对象,这就无法接受了。

在这里插入图片描述
会造成黑色对象变成白色对象,即存活被死亡的方法只有两种:

  • 赋值器插入了一条或多条从黑色对象到白色对象的新引用;
  • 赋值器删除了全部从灰色对象到该白色对象的直接或间接引用。
    所以为了防止出现这问题有两种解决方案:
    增量更新:即破坏第一个条件,黑色插入白色引用后,就将黑色置灰,并记录下来,并发扫描结束后重新在扫描记录的对象。
    原始快照:即破坏第二个条件,即灰色删除指向白色的引用时,将其记录下来,等到并发标记后,再重新扫描记录再扫描灰色的引用。简单来说,快照的意思嘛,无论关系的删除与否,都会按照记录的快照图进行扫描搜索。

总结

本文详细介绍了之前提到的jvm常用术语,希望有助于读者了解到jvm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值