这一篇应该是在垃圾收集器那一篇之前的, 当时由于有些地方不太理解, 一直搁置了, 几天写出来, 仍然有很多自己揣测的地方, 看的朋友可以有选择的采纳.
前面垃圾收集器概述的笔记中已经写过, 通过可达性分析算法 -- 是否有到
达 GC Roots 的引用链来判断, 对象是否可以被回收.
对象之间的引用在类的成员变量初始化以及类的方法中都会出现, 如果逐个遍历, 会消耗很多时间.
虚拟机是怎么做的呢? 使用一组 OopMap 来记录对象在栈中的引用地址, 这样, HotSpot 就可以快速找到 GC Roots 的对象集合.
(Oop:Ordinary Object Pointer, 普通对象指针)
另外, 如果在进行判断分析的时候, 有新的引用产生怎么办呢?
这就要求在虚拟机执行垃圾收集的时候, 需要将所有虚拟机暂停 ("Stop the world"), 以保持快照的一致性.
但是如果积攒了比较多的对象集中进行分析, 那么这个暂停的时间就会比较长, 一次收集的时间就会比较多.
如果通过增加垃圾收集频次, 减少每次垃圾收集分析工作量, 那么垃圾收集占用总的时间也不少.
安全点: 由于为每一条指令都生成 OopMap 需要大量的空间, 所以只再特定的位置记录这些信息, 这些位置成为安全点.
安全点的选定是以 "是否具有让程序长时间执行的特征为标准" 进行选定.
长时间执行的的最明显特征是指令序列复用.
另外, 虚拟机有两种中断方式.
1. 抢先式中断: 由虚拟机发起, 所有线程全部中断, 不在安全点上的线程, 恢复运行至安全点上.
2. 主动式中断: 由线程去轮询是否中断的标志位, 发现标识, 就自己将线程暂停挂起.
HotSpot 采用的是主动式中断的方式.
安全区域 (Safe Region): 在一段代码片段当中, 引用关系不会发生变化.
作用: 专门用来处理当进行垃圾收集的时候, 没有分配 CPU 时间的程序, 比如线程处于 Sleep 状态, 这些线程没办法响应 JVM 的暂停要求, 对于这种状况, 单独设置了一个安全区域.
基本思路: 1. 当线程执行到安全区域中的代码时, 标识自己进入了安全区域.
2. 当线程准备离开安全区域的时候, 检查垃圾收集是否完成, 如果结束了, 线程继续执行; 如果没结束, 就等到结束之后再离开安全区域.
喜欢文章或想一起学习的朋友可以关注我, 给我点赞, 我将会持续更新, 有什么疑问或文中有不当之处请给我留言, 真诚地希望能与大家一起交流探讨, 学习进步.
来源: http://www.jianshu.com/p/c06b98cc787a