Java程序(Tomcat)不断消耗内存(RES在顶部)

Java程序(Tomcat)不断消耗内存(RES在顶部),java,memory-leaks,cpu-usage,Java,Memory Leaks,Cpu Usage,我在一台4 cpu、32GB内存的64位机器上运行Tomcat(操作系统是CentOS 6.3)。我启动Tomcat时使用的Java选项是-server-Xms1024m-Xmx1024m-XX:PermSize=512m-XX:MaxPermSize=512m 一开始,使用top时,RES只有810MB,并且它一直在增加。在此期间,我运行jmap-J-d64-histo-pID检查Java内存堆,我认为gc工作正常,因为堆峰值为510MB,gc之后大约为200MB。但当top中的RES达到1.

我在一台4 cpu、32GB内存的64位机器上运行Tomcat(操作系统是CentOS 6.3)。我启动Tomcat时使用的Java选项是
-server-Xms1024m-Xmx1024m-XX:PermSize=512m-XX:MaxPermSize=512m

一开始,使用top时,RES只有810MB,并且它一直在增加。在此期间,我运行
jmap-J-d64-histo-pID
检查Java内存堆,我认为gc工作正常,因为堆峰值为510MB,gc之后大约为200MB。但当top中的RES达到1.1g时,CPU使用率将超过100%,Tomcat将挂起


当CPU使用率为100%时,使用
jstack-pid
查看转储,名为“vm-thread”的线程几乎会消耗100%的CPU。我在谷歌上搜索到,这是JVM gc线程。所以我的问题是:当gc工作正常时,为什么res不断增长?我如何解决这个问题?谢谢。

如果垃圾收集线程以100%的速度旋转,那么它很可能正在尝试执行垃圾收集,但没有一个对象可以被收集,因此您处于垃圾收集死亡螺旋中,它一直在尝试运行,但无法释放任何内存


这可能是因为您的程序内存泄漏,或者是因为您没有给vm足够的内存来处理在正常使用期间加载的对象数量。听起来您有足够的空间来增加堆大小。这可能只会延长你进入死亡漩涡之前的时间,也可能让你进入跑步状态。您需要运行一段时间的测试,以确保您不会只是延迟不可避免的事件。

可能是永久性泄漏。如果您说堆保持在~500Mb,并且-XX:MaxPermSize设置为512Mb,则full permgen将为您提供大约1gb的内存使用量

如果在程序生命周期的后期加载了很多(比如,很多!)JSP,或者经常使用
String.intern()

遵循以下线索进行进一步调查:


此线程用于将gc调整为扫描permgen

谢谢您的回复。pmap/top命令显示内存一直在增加,但jmap显示gc后的堆大约为200MB,其峰值约为550MB。除了堆,java中任何其他类型的内存都可能导致泄漏?即使gc线程为100%,堆仍然在200MB左右?你能在运行时连接jvisualvm来查看垃圾收集模式和堆空间吗?我将内存增加到2048m(-Xmx2048m),当它达到1.2g时,top的RES不会增加。在询问之前,我应该进行更多的尝试。谢谢你的帮助。我看到你已经接受了我的答案。出于好奇,您能简要描述一下原因和具体帮助吗?当gc线程占用超过100%的cpu时,我首先想到的是内存泄漏。但事实是-Xmx1024m对于我的应用程序来说太小了……我犯了一个错误:(我将内存增加到2048m(-Xmx2048m),并且top的RES在达到1.2g时不会增加………那么我猜@digitaljoel的答案更适合接受OK。按照您的建议:)