【问题标题】:How to check heap usage of a running JVM from the command line?如何从命令行检查正在运行的 JVM 的堆使用情况?
【发布时间】:2025-12-20 22:45:11
【问题描述】:

我能否从命令行检查正在运行的 JVM 的堆使用情况,我指的是实际使用情况,而不是 Xmx 分配的最大数量。

我需要它是命令行,因为我无法访问窗口环境,并且我想要基于值的脚本,应用程序在 Jetty 应用程序服务器中运行

【问题讨论】:

    标签: java memory-management garbage-collection jetty jvisualvm


    【解决方案1】:

    你可以使用jstat,比如:

     jstat -gc pid
    

    这里有完整的文档: http://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html

    【讨论】:

    • 谢谢你看起来像我想要的,但可能需要一段时间才能理解所有选项,但我基本上是在寻找使用了多少堆
    • 所以我认为 OU 是关键列,OC 显示已分配的最大值
    • @PaulTaylor 您想要 EU 和 OU 列 - 将它们相加可以得到使用的堆数量。将 EC 和 OC 列相加即可为您分配给堆的数量。
    • 如果 jvm 以一个 linux 用户的身份运行,而你以另一个用户身份登录,你会怎么做?
    【解决方案2】:

    对于 Java 8,您可以使用以下命令行来获取以 kB 为单位的堆空间利用率:

    jstat -gc <PID> | tail -n 1 | awk '{split($0,a," "); sum=a[3]+a[4]+a[6]+a[8]; print sum}'
    

    命令基本总结:

    • S0U:幸存者空间 0 利用率 (kB)。
    • S1U:Survivor 空间 1 利用率 (kB)。
    • 欧盟:伊甸园空间利用率 (kB)。
    • OU:旧空间利用率 (kB)。

    您可能还希望包括元空间和压缩类空间利用率。在这种情况下,您必须将 a[10] 和 a[12] 添加到 awk 总和中。

    【讨论】:

      【解决方案3】:

      一次完成所有程序。基于@Till Schäfer 的回答。

      以 KB 为单位...

      jstat -gc $(ps axf | egrep -i "*/bin/java *" | egrep -v grep | awk '{print $1}') | tail -n 1 | awk '{split($0,a," "); sum=(a[3]+a[4]+a[6]+a[8]+a[10]); printf("%.2f KB\n",sum)}'
      

      以 MB 为单位...

      jstat -gc $(ps axf | egrep -i "*/bin/java *" | egrep -v grep | awk '{print $1}') | tail -n 1 | awk '{split($0,a," "); sum=(a[3]+a[4]+a[6]+a[8]+a[10])/1024; printf("%.2f MB\n",sum)}'
      

      “Awk sum”参考:

       a[1] - S0C
       a[2] - S1C
       a[3] - S0U
       a[4] - S1U
       a[5] - EC
       a[6] - EU
       a[7] - OC
       a[8] - OU
       a[9] - PC
      a[10] - PU
      a[11] - YGC
      a[12] - YGCT
      a[13] - FGC
      a[14] - FGCT
      a[15] - GCT
      

      用于“Awk sum”:

      a[3] -- (S0U) Survivor space 0 utilization (KB).
      a[4] -- (S1U) Survivor space 1 utilization (KB).
      a[6] -- (EU) Eden space utilization (KB).
      a[8] -- (OU) Old space utilization (KB).
      a[10] - (PU) Permanent space utilization (KB).
      

      [参考: https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html ]

      谢谢!

      注意:适用于 OpenJDK!

      进一步的问题:信息有误?

      如果你用ps命令检查内存使用情况,你会看到java进程消耗的更多...

      ps -eo size,pid,user,command --sort -size | egrep -i "*/bin/java *" | egrep -v grep | awk '{ hr=$1/1024 ; printf("%.2f MB ",hr) } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }' | cut -d "" -f2 | cut -d "-" -f1
      

      更新(2021-02-16):

      根据下面的参考资料(和@Till Schäfer 评论)“ps 可以显示 OS 的总保留内存”(已改编)和 “jstat 可以显示堆和堆栈的已用空间” (改编)。因此,我们看到ps 命令和jstat 命令所指出的内容之间存在差异。

      根据我们的理解,最“真实”的信息将是ps 输出,因为我们将对系统内存受损程度做出有效响应。命令jstat 用于更详细地分析java 在消耗OS 保留内存方面的性能。

      [参考: http://www.openkb.info/2014/06/how-to-check-java-memory-usage.html ]

      【讨论】:

      • 你为什么还要对 YGCT 求和?是时候了
      • 关于您的问题: ps 显示分配的系统内存,而不是堆使用情况。因此,java 可能会分配未使用的内存。
      • java pid rereaval 不适用于多个 java 进程。最好像for pid in $(ps -o pid= -C java); do [...] done 那样做somthink 或使用jps -m
      • @TillSchäfer 我不太明白你所说的$(ps -o pid= -C java); do [...] done 是什么意思...你能给我们看一个完整的例子来说明你想要解释的内容吗?所以我可以进一步丰富我的答案。谢谢! =D
      • @Gamby 调整!谢谢! =D
      【解决方案4】:

      如果您在开启 gc 日志记录的情况下开始执行,您将获得存档信息。 否则'jmap -heap'会给你你想要的。 请参阅jmap doc page 了解更多信息。

      请注意,除非绝对需要,否则jmap 不应在生产环境中使用,因为该工具会暂停应用程序以确定实际的堆使用情况。通常这在生产环境中是不需要的。

      【讨论】:

        【解决方案5】:

        如果你使用的是 JDK 8 及以上版本,请使用 jcmd:

        jcmd GC.heap_info

        【讨论】: