【问题标题】:Java process memory usage (jcmd vs pmap)Java 进程内存使用情况(jcmd 与 pmap)
【发布时间】:2016-09-25 07:33:26
【问题描述】:

我有一个在 Docker 容器内的 Java 8 上运行的 Java 应用程序。该过程启动了一个 Jetty 9 服务器,并且正在部署一个 Web 应用程序。传递了以下 JVM 选项:-Xms768m -Xmx768m

最近注意到进程消耗大量内存:

$ ps aux 1
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
app          1  0.1 48.9 5268992 2989492 ?     Ssl  Sep23   4:47 java -server ...

$ pmap -x 1
Address           Kbytes     RSS   Dirty Mode  Mapping
...
total kB         5280504 2994384 2980776

$ jcmd 1 VM.native_memory summary
1:

Native Memory Tracking:

Total: reserved=1378791KB, committed=1049931KB
-                 Java Heap (reserved=786432KB, committed=786432KB)
                            (mmap: reserved=786432KB, committed=786432KB) 

-                     Class (reserved=220113KB, committed=101073KB)
                            (classes #17246)
                            (malloc=7121KB #25927) 
                            (mmap: reserved=212992KB, committed=93952KB) 

-                    Thread (reserved=47684KB, committed=47684KB)
                            (thread #47)
                            (stack: reserved=47288KB, committed=47288KB)
                            (malloc=150KB #236) 
                            (arena=246KB #92)

-                      Code (reserved=257980KB, committed=48160KB)
                            (malloc=8380KB #11150) 
                            (mmap: reserved=249600KB, committed=39780KB) 

-                        GC (reserved=34513KB, committed=34513KB)
                            (malloc=5777KB #280) 
                            (mmap: reserved=28736KB, committed=28736KB) 

-                  Compiler (reserved=276KB, committed=276KB)
                            (malloc=146KB #398) 
                            (arena=131KB #3)

-                  Internal (reserved=8247KB, committed=8247KB)
                            (malloc=8215KB #20172) 
                            (mmap: reserved=32KB, committed=32KB) 

-                    Symbol (reserved=19338KB, committed=19338KB)
                            (malloc=16805KB #184025) 
                            (arena=2533KB #1)

-    Native Memory Tracking (reserved=4019KB, committed=4019KB)
                            (malloc=186KB #2933) 
                            (tracking overhead=3833KB)

-               Arena Chunk (reserved=187KB, committed=187KB)
                            (malloc=187KB) 

如您所见,RSS (2.8GB) 与 VM 本机内存统计数据实际显示的内容(提交 1.0GB,保留 1.3GB)之间存在巨大差异。

为什么会有这么大的差异?我知道 RSS 还显示了共享库的内存分配,但在分析了 pmap 详细输出后,我意识到这不是共享库问题,而是被称为 [anon] 结构的某些东西消耗了内存。为什么JVM分配了这么多匿名内存块?

我正在搜索并发现以下主题: Why does a JVM report more committed memory than the linux process resident set size? 但是,此处描述的情况有所不同,因为 RSS 显示的内存使用量少于 JVM 统计信息。我有相反的情况,无法弄清楚原因。

【问题讨论】:

  • 我有同样的问题,我有一个带有 Xmx 1.5g (Oracle Jvm) 的 java 进程,当我在 TOP 命令中看到时,它消耗了大约 3.1 g,但是当我在 openjdk 中运行时,它消耗了相同的应用程序大约2.3gb(仍然高于分配的xmx),我还没有找到答案。如果您找到解决方案,请告诉我。谢谢

标签: java memory jvm pmap


【解决方案1】:

我的 Apache Spark 作业之一遇到了类似的问题,我们将应用程序作为胖 jar 提交,在分析线程转储后,我们认为 Hibernate 是罪魁祸首,我们曾经在启动应用程序时加载休眠类实际上是使用java.util.zip.Inflater.inflateBytes 来读取休眠类文件,这超出了我们本机常驻内存使用量几乎 1.5 GB,这是休眠中针对此问题提出的错误 https://hibernate.atlassian.net/browse/HHH-10938?attachmentOrder=desc,cmets 中建议的补丁对我们有用,希望对我们有帮助。

【讨论】:

  • 我们正在使用 Jetty 并部署包含所有依赖项的“胖”WAR。如果我们部署“瘦”JAR 并将所有依赖项复制到 Jetty 库,它就解决了问题。看起来大多数 Web 应用程序服务器都有类似的问题。
  • @Konrad 你能否解释一下你所说的瘦 jar 是什么意思并复制所有依赖项。我正在使用码头并且遇到高非堆内存使用率。
  • 瘦 JAR 是指它只包含: - 编译的类 - 资源 其他依赖项(所有其他 JAR 文件)被复制到 jetty lib 目录。在这种情况下,当 Jetty 启动应用程序时,它不必在应用程序 JAR/WAR 中查找依赖项,也不必将其提取到某种临时目录中。它只是进入他自己的 lib 目录和依赖项。
【解决方案2】:

根据以下文章深度分析后:https://gdstechnology.blog.gov.uk/2015/12/11/using-jemalloc-to-get-to-the-bottom-of-a-memory-leak/ 我们发现问题与 java.util.zip.Inflater 的内存分配有关。

仍然需要找出调用 java.util.zip.Inflater.inflateBytes 并寻找可能的解决方案。

【讨论】:

    【解决方案3】:

    NMT 只跟踪 JVM 管理的部分内存,它不跟踪本机 3rd 方库或内存映射/直接字节缓冲区使用的内存。

    【讨论】:

    • 您能推荐任何简单的方法来查看它吗?我快速查看了进程内存转储,但没有发现任何可疑之处。
    • visualvm 可以监控 DBB 使用情况。 blogs.oracle.com/alanb/entry/monitoring_direct_buffers
    • 我看不到 NIO 映射/直接字节缓冲区的任何重要使用。在这里您可以看到直接缓冲区内存使用情况:direct。对于映射缓冲区,它显示 0。
    • 你有什么其他的想法可以检查吗?
    • 也许你应该发布你的 pmap -x 输出
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    • 2023-03-24
    • 2010-10-19
    • 2016-05-30
    • 1970-01-01
    • 2011-03-09
    相关资源
    最近更新 更多