safepoint又称为安全点,它是JVM中的一个重要概念。
safepoint和JVM GC的爱恨情仇
有了安全点的设定,也就决定了用户程序执行时并非在代码指令流的任意位置都能够停顿下来开始垃圾收集,而是强制要求必须执行到达安全点才能够暂停。
HotSpot虚拟机为了避免安全点过多带来过重的负担,对循环还有一项优化措施,认为循环次数较少的话,执行时间应该也不会太长,所以使用int类型或范围更小的数据类型作为索引值的循环默认是不会被放置安全点的。这种循环被称为可数循环(Counted Loop),相对应地,使用long或者范围更大的数据类型作为索引值的循环就被称为不可数循环(Uncounted Loop),将会被放置安全点。
在可数循环(Counted Loop)的情况下,HotSpot虚拟机搞了一个优化,就是等循环结束后,线程才会进入安全点。
循环如果没有结束,线程不会进入安全点,GC线程就得等着当前的线程循环结束,进入安全点,才能开始工作
当某线程在执行Native函数的时候,此时该线程在执行JVM管理之外的代码,不能对JVM的执行状态做任何修改,因而JVM要进入safepoint不需要关心它。所以也可以把正在执行native函数的线程看作“已经进入了safepoint”,或者把这种情况叫做“在safe-region里”。
JVM外部要对JVM执行状态做修改必须要通过JNI。所有能修改JVM执行状态的JNI函数在入口处都有safepoint检查,一旦JVM已经发出通知说此时应该已经达到safepoint就会在这些检查的地方停下来把控制权交给JVM。
可数循环和不可数循环
可数循环:for int i就是可数循环
不可数循环:for long i就是不可数循环
Thread.sleep(0);有什么用
a、sleep是一个native方法
b、主线程的Thread.sleep方法从native返回,发现安全点操作正在进行中,于是把自己挂起来,知道操作结束。
c、放置safepoint,避免GC线程长时间等待,从而加长 stop the world的时间的目的。