。原文首发于知乎https://www.zhihu.com/question/57722838
1 SafePoint
1.1 什么是SafePoint
Safepoint是java代码中一个线程可能暂停执行的一个位置,SafePoint保存了其他位置没有的一些运行信息。在这个位置上保存了线程上下文的任何信息,包括对象或者非对象的内部指针。在接收到JVM的进入Stop The World 的信息,在safepoint上,用户线程会被挂起。如果JNI代码想要访问在安全点上的用户线程,那么JNI所在线程也会阻塞直到用户线程离开安全点。因为在安全点上jvm线程信息被很好的描述,所以特别适合做一些全局性的操作,例如代码反优化,线程快照等等。http://peg.hengtiansoft.com/article/jvm-zhong-de-safepoint/
1.2 Safepoint是如何工作的?
在HotSpot虚拟机中,safepoint 协议是主动协作的 。每一个用户线程在安全点 上都会检测一个标志位,来决定自己是否暂停执行。
对于JIT编译后的代码,JIT会在代码特定的位置(通常来说,在方法的返回处和counted loop的结束处)上插入安全点代码。对于解释执行的代码,JVM会设置一个2字节的dispatch tables,解释器执行的时候会经常去检查这个dispatch tables,当有safepoint请求的时候,就会让线程去进行safepoint检查。
1.3 Safepoint的相关总结
翻译自: http://chriskirk.blogspot.com/2013/09/what-is-java-safepoint.html
- 一个线程可以在SafePoint上,也可以不在SafePoint上。一个线程在SafePoint时,它的状态可以安全地其他JVM线程所操作和观测;不在SafePoint时,就不能。
- 在SafePoint上不代表被阻塞(比如:JNI方法就可以在SafePoint上运行),但是被阻塞一定发生在SafePoint上。
- 当JVM决定达到一个全局的SafePoint(也叫做Stop the
World),JVM里面所有的线程都要在SafePoint上并且不能离开,直到JVM让线程允许为止。这对要求所有线程都要被良好的描述的操作(比如CG,代码反优化等等)非常有好处。 - 一些JVM可以持有一些私有的线程到SafePoint上而不需要全局的SafePoint,比如Zing.
- 当你写一些非安全的代码的时候,你必须假设SafePoint有可能发生在任何两个字节码之间。
- 非安全代码的调用并不要求必须有安全点,但是他们可以包含一个或者多个安全点。
- 所有类型的JVM有一些效率非常高的技巧和去快速的穿过SafePoint,线程并不需要真正地进入SafePoint除非虚拟机指示线程这么做。
- 所有的JNI方法都在SafePoint上执行。在安全点,JNI代码都不能改变和观测发起调用JNI代码线程的java机器状态。任何通过JNI
API改变和观测调用线程的状态必须在调用线程离开安全点之后,以及再次进入SafePoint之前的时间内发生。
想了解Sa