【问题标题】:Java memory mystery (do I have a leak)?Java 内存之谜(我是否有泄漏)?
【发布时间】:2010-12-01 07:26:27
【问题描述】:

我有一个在 linux 服务器上运行的独立 Java 问题。我用-Xmx256m 启动了jvm。我连接了一个 JMX 监视器,可以看到堆从未真正超过 256Mb。但是,在我的 linux 系统上,当我运行 top 命令时,我可以看到:

1) 首先,这个进程的RES内存使用量在350Mb左右。为什么?我想这是因为堆外的内存?

2) 其次,该进程的VIRT内存使用量不断增长。它永远不会停止!它现在显示为 2500Mb!那我有泄漏吗?但是堆并没有增加,它只是循环!

最终这会带来一个问题,因为系统的交换会不断增长,最终系统会死掉。

有什么想法吗?


我想问的一个重要问题是,在哪些情况下这可能是我的代码而不是 JVM、内核等的结果。例如,如果线程数不断增长,那是否适合我的观察的描述?有什么类似的东西可以建议我注意吗?

【问题讨论】:

标签: java linux optimization memory heap-memory


【解决方案1】:

几个潜在的问题:

  • 直接分配的缓冲区和内存映射文件分配在 Java 堆之外,不能方便地处理。
  • 为每个新线程保留一个堆栈区域。
  • 永久生成(代码和内部字符串)在通常的堆栈之外。类加载器泄漏可能是个问题(通常在重新加载 web 应用程序时)。
  • C 堆可能正在泄漏。

pmap -x 应该显示你的记忆是如何消失的。

【讨论】:

  • 在我的 pmap -x 中基本上有一长串 pastie.org/629976 的列表。有什么想法吗?
  • 我遇到了类似的问题和同样的输出。原来这是为新线程分配的堆栈空间。 (我有线程泄漏)
【解决方案2】:

交换 Sun 与 IBM JVM 进行测试


  1. RES 将包括代码 + 非头部数据。此外,您认为将存储在堆中的某些东西不是,例如线程堆栈和“类数据”。 (这是定义问题,但代码和类数据由-XX:MaxPermSize= 控制。)

  2. 这听起来像是 JVM 实现、Linux 内核或库 JNI 代码中的内存泄漏。

如果使用 Sun JVM,请尝试 IBM,反之亦然。

我不确定 dlopen 究竟是如何工作的,但如果可能的话,访问系统库的代码可能会反复重新映射相同的东西。

最后,您应该使用ulimit 使系统更早地失败,这样您就可以轻松地重复测试。

【讨论】:

    【解决方案3】:

    WRT #1,RSS 大于堆是正常的。这是因为system libraries and non-Java code are included in the RSS but not the heap size。

    WRT #2,是的,听起来你有某种泄漏。如果系统本身崩溃,您可能会消耗过多的系统资源,如套接字、线程或文件。

    尝试使用 lsof 查看 JVM 打开了哪些文件。随着内存的增加,运行几次。如果 JVM 崩溃,请务必设置 -XX:+HeapDumpOnOutOfMemoryError 选项。

    【讨论】:

      【解决方案4】:

      根据我的经验,Java 中非堆内存泄漏的最常见原因是线程泄漏。

      jvmtop 是一个您可能会觉得有用的工具,它可以让您实时监控堆大小、线程数和其他指标。

      【讨论】:

        【解决方案5】:

        听起来你有泄漏。您不能进行分析以查看哪个功能正在驱动内存吗?不过我不确定。

        【讨论】:

          【解决方案6】:

          如果我不得不在黑暗中试一试,我会说您使用的 JVM 存在内存泄漏。

          【讨论】:

            猜你喜欢
            • 2011-06-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多