我在接受采访时听到了这个问题,无法提供答案。后来我通过互联网搜索,仍然没有找到答案。任何人都可以告诉我,在收集垃圾时,JVM如何在停止世界暂停期间停止线程以及它如何再次运行它们。
答案 0 :(得分:15)
至少对于HotSpot和OpenJDK,JVM使用安全点来停止每个线程中的应用程序流,或者在JITed代码中引入,或者通过更改解释代码的字节码映射(请参阅Alexh Ragozin的this post for更多细节)。
请参阅Gil Tene的this answer,了解为什么在处理世界各地的停顿时,安全点可能是另一个问题。
基于上述资源,以下是Hotspot / OpenJDK中的安全点机制(参见例如safepoint.cpp,第154行)的更多细节(据我理解,我并不自称是专家) ,可能还有Cliff的一些文章点击Azul Systems博客(似乎已经从网站上消失了)。
JVM需要控制来自应用程序的流,因此它取决于线程的当前状态:
<强>阻止强>
JVM已经控制了该线程。
运行已解释的代码
解释器进入一种模式(通过交换其调度表),其中每个字节码评估之前都会进行安全点检查。
运行本机代码(JNI)
JNI代码在安全点运行并且可以继续运行,除非它回调到Java或调用某些特定的JVM方法,此时可能会停止它以防止离开安全点(感谢Nitsan的注释)。
运行已编译的代码
JVM使特定的内存页面(Safepoint Polling页面)不可读,这使得定期读取该页面(由JIT编译器插入到编译的代码中)失败并转到JVM处理程序。
< / LI>在VM中运行或转换状态(在VM中也是如此)
无论如何,流程都会通过安全点检查,因此VM会等待它。
一旦线程处于由JVM控制的安全点,JVM就会阻止它退出。当所有线程都已停止(即世界停止)时,JVM可以执行垃圾收集,然后释放所有恢复执行的线程。
有关更多详细信息,您可以在此期间阅读Nitsan Wakart撰写的blog post on safepoints(其本身有更多参考资料)。