JVM的安全点

HotSpot是目前使用最广泛的JVM。它在实现各种垃圾收集算法时,在具体实现上做了一点小优化。

在可达性分析法中,可以作为GCRoots节点的有四种(虚拟机栈中的引用对象、本地方法栈的引用对象、方法区的静态属性引用变量、方法区的常量引用对象),但是这些内容很大(方法区有时候就有数百M),要想检查完所有符合要求的对象,必定很费时间。另外可达性分析应当是对某瞬间的程序快照进行的,不然一边进行可达性分析,一边程序运行,最后出的结果肯定是牛头不对马尾。这个时间点导致GC进行时必须停顿所有Java执行的线程。

目前Java虚拟机都是采用准确是GC,当执行系统停下来之后,并不需要一个不漏的检查完所有执行上下文和全局的引用位置,而虚拟机有办法直接得到哪些地方存放在对象的引用。在HotSpot中,使用了一组OopMap数据结构来实现这个功能。当一个类加载完之后,HotSpot就把对象哪里是社么类型数据计算出来,在JIT(即时编译)的时候也记录下栈和寄存器哪些位置是引用,这样GC时就可以直接得到有哪些对象的引用。

OopMap(Ordinary Object Pointer)很方便,但它也耗费了空间,不可能为每一条指令都创建一个OopMap只能在特定的位置记录一下,这些位置称为安全点(Safepoint)。也就是说程序并非在任何地方都可以进行GC,只有到达安全点之后才可以GC。安全点的选择不能太少,让GC等待的时间太长,也不能太多而影响正常的程序运行速度。所以安全点的选定基本是以程序“是否具有让程序长时间运行的特征”为标准,例如方法调用、循环跳转、异常跳转等地方,具有这些基本功能的指令才产生安全点。更具体点在HotSpot中,安全点的位置主要在:

1.方法返回之前
2.调用某个方法之后
3.抛出异常的位置
4.循环的末尾

多线程的程序要所有的线程都跑到安全点都停下来。让多线程在安全的都停下来分抢先式中断和主动式中断。

抢先式中断:GC发生时所有的线程都先停下来,然后没有到达安全点的线程让它运行到安全点。目前基本没有使用的。

主动式中断:当GC需要终端线程的时候,不对线程进行操作,而是设置一个标志位,各个线程在执行的时候去轮询这个标志位,发现中断标志为真是就自己挂起。轮询标志的地方和安全点重合,以及创建新对象需要分配内存的地方。安全点可能发生GC,而新对象分配内存的时候也可能发生GC,所以在这些地方设置标志,一旦需要GC立即启用。

但是上面都是程序运行的时候,但假设一个线程一直sleep,不去轮询这个标志位无法响应中断,无法走到安全区的地方挂起,JVM不能一直等这个线程执行。因此就需要安全区域,安全区域是指在一段代码片段中,引用关系不会发生变化,在这个区域中的任意地方开始GC都是安全的,也可以把安全区域看成是一大串的安全点。

在线程执行到安全区域时,首先标记自己已经进入了安全区域,在这段区域要进行GC时就不需要管这些已经标识好的线程。在离开安全区域时,线程要检查自己是否完成了根节点枚举(GC roots)或者整个GC过程。如果完成就可以离开这个区域,否则就必须可以离开这片区域的信号。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值