GC如何挂起/阻止应用程序线程

Sat*_*ish 1 java garbage-collection

我知道当新的对象分配失败或调用System.gc()时会触发GC.每个GC算法都建议,作为第一步,GC线程将挂起所有应用程序线程,以便它们不会影响GC活动.

但我想了解GC如何挂起所有正在运行的线程?我的意思是JVM定义了任何安全点,例如,内存分配(新对象创建)或方法调用,当应用程序线程到达这些安全点时,它们将被阻止以防止GC锁定.这是真的吗?如果是这样,那么如何只执行如下简单计算的应用程序线程(我知道实际上这永远不会发生),它会被暂停吗?

while(true) {
    a = a + s;
    s = s + a;

    // some computation that doesn't touch any JVM safe points 
}
Run Code Online (Sandbox Code Playgroud)

在这些情况下,GC活动是否会在不挂起这些应用程序线程的情况下继续(并在以后尝试跨越安全点时暂停/阻止,例如对象分配)?

但我相信,GC始终等待这些应用程序线程进入安全点并在继续之前暂停它们.我的假设是真的吗?

the*_*472 5

但我想了解GC如何挂起所有正在运行的线程?

热点实现使用安全点轮询.报价:

安全点如何工作?

HotSpot JVM中的安全点协议是协作的.每个应用程序线程都会检查安全点状态,并且需要将自身置于安全状态的安全状态.对于已编译的代码,JIT在某些点(通常是从调用返回或循环的后跳)后的代码中插入安全点检查.对于解释代码,JVM具有两个字节的代码分派表,如果需要安全点,JVM会切换表以启用安全点检查.

安全点状态检查本身以非常狡猾的方式实现.正常的内存变量检查需要昂贵的内存屏障.但是,安全点检查是在内存读取障碍时实现的.然后需要安全点,JVM取消映射页面,该地址在应用程序线程上引发页面错误(由JVM的处理程序处理).这样,HotSpot维护其JITed代码CPU管道友好,但确保正确的内存语义(页面取消映射强制内存屏障处理核心).

来自机械同情邮件列表的更详细描述.


 // some computation that doesn't touch any JVM safe points 
Run Code Online (Sandbox Code Playgroud)

如果编译器可以证明它们在有限的时间内完成,那么编译器只允许这些事情.否则它会插入安全点轮询