并行标记扫描 (CMS) 是停止世界事件吗?

我看到许多课程的卸载,我的整个系统将在那段时间内挂起。

[Unloading class sun.reflect.GeneratedMethodAccessor117]
[Unloading class sun.reflect.GeneratedConstructorAccessor1896]
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor485]
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor579]
.... // about 1700 of them

同时,我没有看到烫发空间的峰值,所以它似乎不是GC事件。

我想知道以下内容

是并发标记扫荡收集一个停止世界事件?

即使烫发空间没有满,也会发生这种情况吗?


答案 1

CMS是一种GC,分为几个阶段

enter image description here

如您所见,两个阶段 - 初始标记和备注是停止世界事件。

来源 : 在部分下。Reviewing Generational GC and CMS

Does it happen even when the perm space is not full?

AFAIK为此你应该有.当烫发面积达到其阈值时,将触发FGC。CMSClassUnloadingEnabledUseConcMarkSweepGC

此外,尽管如果 permgen 区域被填满(并且 GC 仍在处理 permgen 区域),则 Concurrent Sweep(短语 (4)) 不是 STW 事件,这可能会导致停止所有进程线程,并且只有 GC 线程运行,直到回收所有必需的内存。


答案 2

CMS不是一个“事件”。它是一个垃圾回收器。CMS确实有几个阶段,其中所有内容都停止,但在正常情况下,这些阶段非常短(几毫秒)。通常,如果您暂停了很长时间,则意味着CMS无法跟上垃圾生成的速度(在已设置的约束范围内),并且JVM必须使用“标记扫描”收集器执行完整的GC...这是阻止世界。

根据您的 JVM,可能只有在发生完整 GC 时才收集 permgen,而只有在 GC 进行 permgen 时才会收集/卸载类。

但是,您无法推断类卸载会导致长时间的暂停。事实上,如果你的GC统计数据说烫发没有填满,更有可能反过来。

还有一种可能是类卸载的日志记录导致了“停止世界”问题:请参阅 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6637203


观察:

  • 如果你有成千上万条关于卸载动态创建的类的消息,那么我会看看你的系统的架构。是否过度使用代理类?

  • 在Java 8中,permgen消失了,取而代之的是元空间。升级可以缓解您的问题。