突然接到客户反馈生产环境服务器经常会卡死。到生产环境上查看后发现CPU占用率100%,但内存和磁盘使用情况正常。查看服务运行日志,发现一个蹊跷的异常:Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded。施展面向百度编程大法后了解到:该异常是GC占用大量时间为释放很小空间的时候发生的,是一种保护机制。一般是因为堆太小,导致异常的原因:没有足够的内存。
Sun 官方对此的定义:超过98%的时间用来做GC并且回收了不到2%的堆内存时会抛出此异常。
可是服务器是4G内存,出现异常时候内存只用了一半不到。检查tomcat的配置文件,并没有JVM的参数配置。通过以下指令检查检查tomcat设置的最大内存:
通过jps查找tomcat的进程id,然后再通过jinfo命令查看最大内存设置。
[root@tencent_host ~]# jps
23461 Jps
2183 QuorumPeerMain
[root@tencent_host ~]# jinfo -flag MaxHeapSize 2183
-XX:MaxHeapSize=994050048
可以看到tomcat默认jvm实例最大内存为994050048,换算成MB大概是980多MB,MaxHeapSize默认值为最大内存的1/4。原因基本上明确了。又进一步了解到客户最近又增加了一批系统使用用户。980MB的内存对于当前系统并发量来说确实有点捉襟见肘。
最终解决方案:通过jvm参数增大内存,MaxHeapSize设置为3G。
有下面的一些jvm的参数,他们的默认值一般比较容易忽略,记录下来,方便查询:
-Xms 默认情况下堆内存的64分之一
-Xmx 默认情况下堆内存的4分之一
-Xmn 默认情况下堆内存的64分之一
-XX:NewRatio 默认为2
-XX:SurvivorRatio 默认为8
避免Concurrent Mode Failure 年老代剩余空间>=EDEN+SURVIROR,即: (Xmx-Xmn)*(1-CMSInitiatingOccupancyFraction/100)>=(Xmn-Xmn/(SurvivorRatior+2))