Java 同时标记扫描(CMS)是一个停止世界事件吗?
我看到很多课程被卸载,我的整个系统将在这段时间内挂起Java 同时标记扫描(CMS)是一个停止世界事件吗?,java,garbage-collection,jvm,concurrent-mark-sweep,Java,Garbage Collection,Jvm,Concurrent Mark Sweep,我看到很多课程被卸载,我的整个系统将在这段时间内挂起 [Unloading class sun.reflect.GeneratedMethodAccessor117] [Unloading class sun.reflect.GeneratedConstructorAccessor1896] [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor485] [Unloading class sun.reflect
[Unloading class sun.reflect.GeneratedMethodAccessor117]
[Unloading class sun.reflect.GeneratedConstructorAccessor1896]
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor485]
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor579]
.... // about 1700 of them
同时,我在perm空间中没有看到尖峰,所以它似乎不是GC事件
我想知道以下情况
同时进行的Mark Sweep collection是一项世界性活动吗
即使在烫发空间未满时也会发生这种情况吗?CMS是一种GC类型,分为多个阶段 正如你可以看到的两个阶段-初始标记和备注是世界事件的停止 :在查看世代GC和CMS部分下
Does it happen even when the perm space is not full?
为此,您应该使用useConMarkSweepGC
将CMSClassUnloadingEnabled
。当永磁区达到阈值时,FGC将被触发
此外,如果permgen区域被填满(并且GC仍在处理permgen区域),则并发扫描(第(4)段)不是STW事件,但它可能导致停止所有进程线程,并且只有GC线程运行,直到回收所有所需内存。CMS不是“事件”。它是一个垃圾收集器。CMS确实有几个阶段,所有的东西都会停止,但在正常情况下,这些阶段非常短(几毫秒)。一般来说,如果您得到长时间的暂停,这意味着CMS无法跟上垃圾生成的速度(在已设置的约束范围内),并且JVM必须使用“标记扫描”收集器执行完整的GC。。。这就是阻止世界
根据您的JVM,可能只有在完全GC发生时才会收集permgen,并且只有在对permgen进行GC时才会收集/卸载类
但不能推断类卸载导致长时间暂停。事实上,如果您的GC统计数据显示permgen没有填满,则更可能是相反的情况
也有可能是您的类卸载日志导致了“停止世界”问题:请参阅
意见:
- 如果您有数千条关于卸载动态创建的类的消息,那么我将看看您的系统的体系结构。你是否已经不再使用代理类了
- 在Java8中,permgen消失了,取而代之的是元空间。升级可能会缓解您的问题
原因是,Perm通常在加载应用程序中的所有类后稳定。 这可能是挂断的结果。 这意味着,如果JVM没有足够的内存。它尝试使用完整的GC。作为完整gc的一部分,Perm将进行GCed 关于你问的问题 CMS还可以进行完全GC。它只是减少了全GC的#。在小型GC期间,它还收集旧内存区域 在我看来,堆内存中可能有问题,这会导致完全GC和挂起问题。因此,您需要使用可视化JVM工具或某种GC日志分析来检查内存使用情况。您可能会发现旧内存区域已满,JVM试图对其进行GC。但是没有释放足够的内存,它将重试gc。然后重试……等等
我想你可能是内存泄漏了。问题因此,最好是进行GC日志分析,如果是内存泄漏问题,则需要进行堆转储并对其进行分析。我可以假设卸载类sun.reflect->在第(4)段中吗?此文本副本无助于回答OP的特定问题。请参阅,它可能是相关的。这些消息的打印可能是挂起的原因(即使没有提到关闭
stdout
)。您使用的是旧版本的Java运行时吗?“Perm通常在所有类…加载后稳定”可能适用于某些应用程序,但显然不是OP,它显示了在运行时通过反射API中的优化(称为膨胀)生成的临时类的卸载。这一点也不奇怪,大多数应用程序都会出于某种目的动态生成字节码。