如果你的JDK正好是上面这些版本,强烈建议升级到更新BUG已经修复的版本。
5. 显示System.gc调用
检查是否有显示的System.gc调用,应用中的一些类里,或者第三方模块中调用System.gc调用从而触发STW的FullGC,也可能会引起非常长时间的停顿。如下GC日志所示,Full GC后面的(System)表示它是由调用System.GC触发的FullGC,并且耗时5.75秒:
如果你使用了RMI,能观察到固定时间间隔的FullGC,也是由于RMI的实现调用了System.gc。这个时间间隔可以通过系统属性配置:
JDK 1.4.2和5.0的默认值是60000毫秒,即1分钟;JDK6以及以后的版本,默认值是3600000毫秒,即1个小时。
如果你要关闭通过调用System.gc()触发FullGC,配置JVM参数 -XX: DisableExplicitGC即可。
那么如何定位并解决这类问题问题呢?
- 配置JVM参数:-XX: PrintGCDetails -XX: PrintHeapAtGC -XX: PrintGCTimeStamps -XX: PrintGCDateStamps and -XX: PrintGCApplicationStoppedTime. 如果是CMS,还需要添加-XX:PrintFLSStatistics=2,然后收集GC日志。因为GC日志能告诉我们GC频率,是否长时间停顿等重要信息。
- 使用vmstat, iostat, netstat和mpstat等工具监控系统全方位健康状况。
- 使用GCHisto工具可视化分析GC日志,弄明白消耗了很长时间的GC,以及这些GC的出现是否有一定的规律。
- 尝试从GC日志中能否找出一下JVM堆碎片化的表征。
- 监控指定应用的堆大小是否足够。
- 检查你运行的JVM版本,是否有与长时间停顿相关的BUG,然后升级到修复问题的最新JDK。