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

时间:2015-06-07 06:15:11

标签: 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 
}

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

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

1 个答案:

答案 0 :(得分:5)

  

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

热点实施使用safepoint polling。引用:

  

安全点如何运作?

     

HotSpot JVM中的安全点协议是   协作。每个应用程序线程检查安全点状态和   需要将自己停放在安全状态的安全状态。对于编译代码,   JIT在某些点(通常是在之后)插入代码中的安全点检查   从呼叫返回或在循环的后跳)。对于解释代码,JVM   有两个字节的代码调度表,如果需要safepoint,则为JVM   切换表以启用安全点检查。

     

安全点状态检查   本身是以非常狡猾的方式实现的。正常的记忆变量   检查需要昂贵的记忆障碍。虽然,安全点检查   实现为内存读取障碍。然后需要安全点,   JVM取消映射该地址,导致应用程序出现页面错误   线程(由JVM的处理程序处理)。这样,HotSpot   保持其JITed代码CPU管道友好,但确保正确   内存语义(页面unmap强制内存屏障处理   芯)。

来自机械同情邮件列表的

more detailed description

 // some computation that doesn't touch any JVM safe points 

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