## 枚举根节点、安全点、安全区域
在根可达性分析算法中,从GC Roots集合中找引用链是虚拟机高效实现的第一个例子。
### 问题一:为什么要枚举根节点?怎么高效实现?
![](https://img.kancloud.cn/50/07/500702775b23ca7437a7fca64518c486_1538x820.png)
虽然GC Roots的节点主要在全局性的引用(例如常量或者类静态变量)与执行上下文(例如栈帧中的局部变量表),但是查找起来并发容易的事。
### 问题一解决之道:使用根可达分析算法判断垃圾,所以需要枚举根节点。通过在安全点生成并维护OopMap来高效计算GC Roots集合。
为了解决某个时刻GC Roots集合的定位问题,在HotSpot中,有个数据结构(映射表)称为**OopMap**。一旦类加载动作完成的时候,HotSpot就会把对象内什么偏移量上是什么类型的数据计算出来,记录到OopMap。在即时编译过程中,也会在**特定的位置**生成 OopMap,记录下栈上和寄存器里哪些位置是引用。这样在垃圾收集器在**枚举根节点**时,就可以通过扫描OopMap中的对象快速得到当时的GC Roots集合。
(每个安全点都会生成对应的OopMap)
### 问题二:为什么需要安全点?安全点在哪些位置?
进行垃圾回收的过程中,会涉及对象的移动。为了保证对象引用更新的正确性,必须暂停所有的用户线程(会发生STW)。线程并不是在任意位置都能中断挂起的,只有在特定的位置才行。
这些特定的位置:
* 方法调用
* 循环跳转(非 counted 循环,固定循环次数)
* 异常跳转
称之为**安全点**(每个安全点都会生成对应的OopMap),垃圾收集时,需要用户线程到达安全点停下来后才开始执行。
在HotSpot中,采用主动式中断的思想让做垃圾收集时让所有用户现在都跑到最近安全点停顿下来。
是在安全点和分配对象时设置一个中断标志,各线程执行时会不停轮询这个标志,一旦发现为真时就在最近安全点主动挂起。
### 问题三:为什么需要安全区域?
安全点的设计几乎完美解决如何停顿用户线程,让虚拟机进入垃圾回收状态。可如果用户线程处于Sleep或者Blocked状态时,线程是无法响应中断请求的,虚拟机也不可能等待线程被激活后走到安全点挂起自己,这个时候就需要安全区域来解决了。
**安全区域**是指能够确定在某一段代码之中,引用关系不会发生变化,因此这个区域内任意地方开始垃圾回收都是安全的。(安全区域是扩展了的安全点)
- 面试突击
- Java虚拟机
- 认识字节码
- 000Java发展历史
- 000Macos10.15.7上编译OpenJDK8u
- 001熟悉Java内存区域
- 002熟悉HotSpot中的对象
- 003Java如何计算对象大小
- 004垃圾判定算法与4大引用
- 005回收堆和方法区中对象
- 006垃圾收集算法
- 007HotSpot虚拟机垃圾算法实现篇1
- 007HotSpot虚拟机垃圾算法实现篇2
- 007HotSpot虚拟机垃圾算法实现篇3
- 008垃圾收集器
- 009内存分配与回收策略
- 010Java虚拟机相关工具
- 011调优案例分析
- 012一次IDEA的启动速度调优
- 013类文件Class的结构
- 014熟悉字节码指令
- 015类加载机制(过程)
- 016类加载器
- IDEA的JVM参数
- Java基础
- Java自动装箱与拆箱
- Java基础数据类型
- Java方法的参数传递
- Java并发
- 001走入并行的世界
- 002并行程序基础
- 003熟悉Java内存模型JMM
- 004Java并发之volatile关键字
- 005线程池入门到精通
- 006Java多线程间的同步控制方法
- 007Java维基准测试框架JMH
- 008Java并发容器
- 009Java的线程实现
- 010Java关键字synchronized
- 011一些并行模式的熟悉
- 单例模式和不变模式
- 生产者消费者模式
- Future模式
- 012一些并行算法的熟悉
- 面试总结
- 长亮一面