关于JVM Safepoint(安全点)的理解
2020-04-07
1,907 views
1 min read
首先从垃圾回收说起,当发生GC时,需要从方法区或本地变量表等地方获取GC Roots
,但如果是单纯的遍历查找的话是非常亏的,GC发生时本身就停止了所有的线程,不能让这一操作耗费太多的时间。
HotSpot为优化GC Roots
的查找,采用了OopMap
这一数据结构,一旦类加载动作完成的时候,HotSpot就会把对象内什么偏移量上是什么类型的数据计算出来,在即时编译过程中,也会在特定的位置记录下栈里和寄存器里哪些位置是引用。
通过OopMap
,JVM可以快速枚举出GC Roots
,但是对象引用随时都在变,如何维护OopMap
又是一个问题。HotSpot的做法就是设置Safepoint
。在一个方法中往往有一个或多个安全点,这些安全点把一个方法分割成了多个段,每一段都有一个OopMap
,仅当线程执行到达安全点时,才能执行GC。
多线程下,发生GC时,每一个线程在到达安全点时都会挂起(这个功能通过线程的轮询实现)。当所有线程都被挂起后,才能执行GC操作。
当线程无法响应虚拟机的中断请求时,比如Sleep
或者Blocked
状态,线程不能走到安全点挂起自己,虚拟机也不可能等他被重新激活,所以又引入了一个Safe Region
安全区域来解决。当一段代码中,引用关系不会发生变化时(比如从线程Sleep
到被激活的这段时间),称这段代码为安全区域,处在安全区域的线程在发生GC时会继续执行,如果执行到安全区域末尾时,GC仍未结束,则会挂起并等待GC结束。如果GC已经结束,则会当作无事发生接着执行下面的代码。
Previous Post
JVM的类加载
Next Post
当Java对象处在偏向锁、轻量锁、重量级锁状态时,Mark Word值存储在哪?
Or you can contact me by Email