JVM一分钟的垃圾回收

6
如下所示,正常工作中出现了一个停止全球的GC操作,持续时间超过60秒。可以确定,在此期间(terracotta)客户端掉线并抱怨(terracotta服务器)未在此期间响应,因此可以将其视为整个时间段的暂停。
这是年轻/次要GC吗?如果是,是否可能是由于年轻代(伊甸园和幸存者)中的饥饿引起的?
只有109333(KB)被释放了吗?
我将开始绘制不同的内存容器图表,您还有什么其他建议可以进一步诊断此类问题?
date, startMem=24589884, endMem=24478495, reclaimed=111389, timeTaken=0.211244 (1172274.139: [GC 24589884K->24478495K(29343104K), 0.2112440 secs])
date, startMem=24614815, endMem=24505482, reclaimed=109333, timeTaken=61.301987 (1172276.518: [GC 24614815K->24505482K(29343104K), 61.3019860 secs])
date, startMem=24641802, endMem=24529546, reclaimed=112256, timeTaken=2.68437 (1172348.921: [GC 24641802K->24529546K(29343104K), 2.6843700 secs])

使用以下配置,Sun JVM 版本为1.6:

-Xms28672m -Xmx28672m -XX:+UseConcMarkSweepGC -XX:+PrintGCTimeStamps -XX:+PrintGC

针对GC进一步调试的合理配置调整:

'-XX:+PrintGCDateStamps' Print date stamps instead of relative timestamps
'-XX:+PrintGCDetails' Will show what cpu went for (user, kern), gc algorithm used 
'-XX:+PrintHeapAtGC' will show all of the heaps memory containers and their usage
'-Xloggc:/path/to/dedicated.log' log to specific file

你的应用程序在做什么?当大量内存在多次扫描中从堆中回收时,会发生GC抖动。可能每个扫描都导致更多的对象变得可回收,进而导致更多的扫描。即使是你展示的2秒运行时间对于GC来说也是巨大的。我认为你会发现改变你的应用程序处理对象的方式,而不是JVM配置,是你需要采取的路径。任何需要保持GC抖动最小的应用程序都应该考虑重复使用而不是重新分配对象。 - codeghost
这是一个会话(cookie)存储。例如,“reclaimed”表示实际上没有回收多少内存。如果是这样,知道原因就非常方便。我完全同意您的观点,需要解决如何处理(会话)对象、它们包含什么等问题。有一个更好地处理会话的过程,但目前我的工作是找出为什么GC需要60秒以上,而仍然不能释放比之前0.2秒GC更多的内存。 - user135361
2
看一下这篇博客 http://kirk.blog-city.com/why_do_i_have_this_long_gc_pause.htm 可能会给你一些指示。 - codeghost
1个回答

1

-XX:+UseConcMarkSweepGC 启用并发收集

Default Vs. CMS

总时间是停止JVM阶段(JVM阻塞)和并发阶段(JVM执行用户代码)的总和。
您应该启用详细的GC日志记录以进一步调查,因为您没有关于那60秒中有多少个阻止JVM的信息。

我已经概述了更详细的输出将被记录。问题不在于CMS如何工作,而是在什么情况下会发生长时间的停顿。JVM一直被阻塞,因此这是一个“major GC”,很可能是由于碎片整理引起的。如果是这样,问题是如何知道增加堆大小是否有帮助,或者在什么情况下调度CMS提前启动会有帮助。我感谢你的尝试,但在我点赞之前,你必须尝试分离因素。 - user135361
2
你怎么知道JVM一直被阻塞,没有详细的日志记录?你应该将所有信息添加到问题中。 - fglez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接