5

我在 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。但是当 RES in top hit 1.1g 时,CPU 使用率会超过 100%,Tomcat 会挂掉。

用于在 CPU使用jstack pid率为 100% 时查看转储,名为“vm 线程”的线程几乎占用了 100% 的 CPU。我用谷歌搜索,它是 JVM gc 线程。所以我的问题是:为什么当 gc 工作正常时 res 会继续增长?我该如何解决这个问题?谢谢。

4

2 回答 2

2

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

如果您在程序生命周期的后期加载了很多(比如,很多!)jsps,或者您使用String.intern()了很多,则可能会发生这种情况。

请按照此线程进行进一步调查:如何转储 Permgen?

而这个用于调整 gc 以扫描 permgen 的线程JVM 标志 CMSClassUnloadingEnabled 实际上是做什么的?

于 2012-12-05T04:41:02.020 回答
1

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

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

于 2012-12-05T03:52:26.537 回答