15

我看到许多卸载类,我的整个系统将在那段时间挂起..

[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 事件。

我想知道以下

Concurrent Mark Sweep 收集是停止世界事件吗?

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

4

3 回答 3

22

CMS 是 GC 的一种,分为阶段

在此处输入图像描述

正如您所看到的两个阶段 - 初始标记和备注是停止世界事件。

来源:根据Reviewing Generational GC and CMS部分。

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

为此,您应该CMSClassUnloadingEnabled拥有UseConcMarkSweepGC. 当永久区域达到其阈值时,将触发 FGC。

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

于 2014-01-20T09:27:46.873 回答
5

CMS 不是“事件”。它是一个垃圾收集器。CMS 确实有几个阶段会停止一切,但在正常情况下,这些阶段非常短(几毫秒)。一般来说,如果你得到一个长时间的停顿,这意味着 CMS 无法跟上垃圾生成的速度(在已设置的约束范围内),并且 JVM 必须使用“ mark-sweep”收集器......这阻止世界。

根据您的 JVM,可能仅在发生完整 GC 时才收集 permgen,并且仅在 permgen 被 GC 时才收集/卸载类。

但是你不能推断类卸载会导致长时间的停顿。事实上,如果你的 GC 统计数据显示 permgen 没有填满,则更有可能是相反的情况。

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


观察:

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

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

于 2014-01-20T10:36:04.293 回答
1

通常 perm gc 不会造成挂断问题。

原因是,Perm 通常在应用程序中的所有类都已加载后稳定下来。这可能是挂断的结果。这意味着,如果 JVM 没有足够的内存。它尝试进行 Full-GC。作为完整 gc 的一部分,Perm 将被 GC。

关于你问的问题 CMS 也会产生 Full GC。它只是减少了 Full GC 的数量。在 Minor GC 期间,它还会收集 Old 内存区域。

在我看来,您可能在堆内存中遇到问题,它会导致 # 次 Full GC 并导致挂起问题。所以你需要使用 Visual JVM 工具或一些 GC 日志分析来检查内存使用情况。您可能会发现 Old 内存区域已满,JVM 尝试对它进行 GC。但是没有释放足够的内存,它会重试 gc 。并重试重试..等。

我想你可能有内存泄漏。问题。所以最好进行 GC 日志分析,如果是内存泄漏问题,则需要进行堆转储并进行分析。

于 2014-01-20T13:39:09.763 回答