【问题标题】:Java program (Tomcat) keeps eating memory (RES in top)Java 程序(Tomcat)不断消耗内存(RES 在顶部)
【发布时间】:2012-11-22 20:23:54
【问题描述】:

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

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

【问题讨论】:

  • 我看到你已经接受了我的回答。出于好奇,能否请您简要描述一下原因以及具体有什么帮助?
  • 当 gc 线程占用超过 100% cpu 时,我首先想到的是内存泄漏。但事实是 -Xmx1024m 对我的应用程序来说太小了.....我犯了一个错误:(我把内存增加到2048m(-Xmx2048m),top的RES到了1.2g就没有增加......
  • 那我猜@digitaljoel 的回答更适合接受
  • 好的。听从了你的建议:)

标签: java memory-leaks cpu-usage


【解决方案1】:

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

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

关注此主题以进行进一步调查:How to dump Permgen?

还有这个线程用于调整 gc 以扫描 permgen What does JVM flag CMSClassUnloadingEnabled actually do?

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 感谢您的回复。 pmap/top 命令显示内存不断增加,但 jmap 显示 gc 后堆只有 200MB 左右,峰值约为 550MB。除了堆之外,java 中的任何其他类型的内存都会导致泄漏吗?
    • 即使 gc 线程为 100%,堆仍然在 200MB 左右?可以在运行时附加 jvisualvm 来查看垃圾收集模式和堆空间吗?
    • ,我把内存增加到2048m(-Xmx2048m),到1.2g的时候top的RES没有增加。我应该多试一下再问。谢谢你的帮助。
    猜你喜欢
    • 2011-10-03
    • 1970-01-01
    • 2012-03-21
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    相关资源
    最近更新 更多