我在4-cpu和32GB内存64位机器上运行Tomcat(操作系统是CentOS 6.3)。我启动Tomcat的Java选项是-server -Xms1024m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m
一开始,RES只有810MB使用top,并且它不断增加。在此期间,我运行jmap -J-d64 -histo pID
检查Java内存堆,我认为gc工作正常,因为堆峰值为510MB,gc后约为200MB。但是当顶部的RES达到1.1g时,CPU使用率将超过100%并且Tomcat将挂起。
当CPU使用率为100%时,使用jstack pid
查看转储,名为“vm thread”的线程几乎占用了100%的CPU。我用Google搜索,它是JVM gc线程。所以我的问题是:当gc工作正常时,为什么res会继续增长?我怎么能解决这个问题?感谢。
答案 0 :(得分:2)
可能是一个permgen泄漏。如果你说你的堆保持在~500Mb,并且-XX:MaxPermSize设置为512Mb,那么完整的permgen将为你提供大约1GB的内存使用量。
如果您在程序的生命周期中稍后加载了很多(比如,很多!)jsps,或者您已经使用了String.intern()
,那么可能会发生这种情况。
请按照此主题进行进一步调查:How to dump Permgen?
此线程用于调整gc以扫描permgen What does JVM flag CMSClassUnloadingEnabled actually do?
答案 1 :(得分:1)
如果垃圾收集线程以100%旋转,则可能是它正在尝试执行垃圾收集,但是没有一个对象可以被收集,因此您处于垃圾收集死亡螺旋中,它一直在尝试运行但不是能释放任何记忆。
这可能是因为您的程序中存在内存泄漏,或者因为您没有给vm足够的内存来处理正常使用期间加载的对象数。听起来你有足够的空间来增加堆大小。这可能只会延长您达到死亡螺旋线之前的时间,或者它可能会使您进入运行状态。你会想要进行一段时间的测试,以确保你不仅仅是推迟了不可避免的事情。