我明白,当一个新的对象分配失败或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总是等待这些应用程序的线程进入安全点,继续之前暂停它们。 是我的假设是真的吗?
不过,我想了解如何GC暂停所有正在运行的线程?
热点实现使用还原点投票 。 报价:
safepoints是如何工作的?
在热点JVM还原点协议是协作。 在还原点的每个应用程序线程检查还原点状态和公园本身处于安全状态是必需的。 对于编译代码,JIT插入还原点检查在某些点代码(通常情况下,从调用返回之后或在循环的背越式跳高)。 为了解释的代码,JVM有两个字节码分派表,如果需要还原点,JVM切换表,以启用还原点检查。
还原点状态检查本身是非常狡猾的方式来实现。 普通内存变量检查将需要昂贵的记忆障碍。 但是,作为存储器读屏障还原点检查实现。 然后还原点是必需的,JVM取消映射页面上的应用程序的线程地址挑起页面错误(这是由JVM的处理程序处理)。 这样一来,热点保持其JIT编译的代码CPU流水线友好,但确保正确的内存语义(页面取消映射迫使记忆障碍处理核心)。
更详细的描述从机械同情邮件列表。
// some computation that doesn't touch any JVM safe points
编译器只允许那些东西,如果它能够证明他们在有限的时间量完成。 否则它插入还原点调查