bigywater.tech
Java · 345

jmap:堆直方图与堆转储

堆转储是线上排查最重的一刀。这篇用同样的堆状态,把 jmap 的直方图和转储在「含不含垃圾」「触不触发 GC」「文件多大」「应用停多久」几方面逐项量出来,并对照 jcmd。

454.1 vs 137.2 MB
jmap -dump 与 jmap -dump:live 的 hprof 文件大小(堆里有 300 万个垃圾对象)
263 vs 43 ms
两种转储期间应用线程 5 ms 心跳的最大间隔
jcmd 默认 live
jcmd GC.heap_dump 不带 -all 时的行为(Old GC 计数 +1);与 jmap 默认含垃圾相反

jmap -histo 与 -histo:live

实测 · 本机执行输出
  [jmap -histo] 耗时 0.22 s;Total 6645923 个对象 / 387 MB;GC 计数 GC Young=0 Conc=0 Old=0 → GC Young=0 Conc=0 Old=0
     2: 3000000 96000000 Main$Garbage
     3: 300000 9600000 Main$Live
     1: 3310668 290290680 [B (java.base@21.0.12.1)
  [jmap -histo:live] 耗时 0.09 s;Total 631197 个对象 / 127 MB;GC 计数 GC Young=0 Conc=0 Old=0 → GC Young=0 Conc=0 Old=1
     235: 1 32 Main$Garbage
     2: 300000 9600000 Main$Live
     1: 308296 122032696 [B (java.base@21.0.12.1)

jmap -dump 与 :live

实测 · 本机执行输出
  [-dump:format=b] 耗时 0.43 s;文件 454.1 MB;文件头 “JAVA PROFILE 1.0.2”;jmap 输出:Heap dump file created [476119052 bytes in 0.262 secs];GC 计数 GC Young=0 Conc=0 Old=0 → GC Young=0 Conc=0 Old=0;GAP 263
  [-dump:live,format=b] 耗时 0.21 s;文件 137.2 MB;文件头 “JAVA PROFILE 1.0.2”;jmap 输出:Heap dump file created [143817948 bytes in 0.043 secs];GC 计数 GC Young=0 Conc=0 Old=0 → GC Young=0 Conc=0 Old=1;GAP 43
  live / all 文件大小比:0.30
  对照(什么都不做 1.5 秒):最大间隔 GAP 7
  jmap -histo(含不可达)期间:最大间隔 GAP 39(耗时 0.26 s)

路径与覆盖

实测 · 本机执行输出
  jmap 的工作目录是 sub/,目标 JVM 的工作目录是 j205a/;file=rel.hprof → Heap dump file created [475230224 bytes in 0.243 secs]
    rel.hprof 出现在目标 JVM 的目录: False ;出现在 jmap 的目录: True
  再转储到同一个文件名:
    Dumping heap to <dir>/sub/rel.hprof ...
    Unable to create <dir>/sub/rel.hprof: File exists

其它选项

实测 · 本机执行输出
  jmap -clstats:8 行;前 3 行:
    ClassLoader         Parent              CLD*               Classes   ChunkSz   BlockSz  Type
    0x0000008800069008  0x0000000000000000  0x000000783cfa0780       0         0         0  jdk.internal.loader.ClassLoaders$PlatformC
    0x0000000000000000  0x0000000000000000  0x000000783cfa0140     696   4456448    452240  <boot class loader>
  jmap -heap:
    Error: -heap option used
    Cannot connect to core dump or remote debug server. Use jhsdb jmap instead
  jmap -finalizerinfo:
    No instances waiting for finalization found
  jmap -histo:foo(不存在的子选项):
    Fail: invalid option: 'foo'
    Usage:
        jmap -clstats <pid>

对照 jcmd GC.heap_dump

实测 · 本机执行输出
  jmap -dump:format=b        耗时 0.47 s;文件 454.1 MB;GC 计数 GC Young=0 Conc=0 Old=0 → GC Young=0 Conc=0 Old=0
  jmap -dump:live,format=b   耗时 0.24 s;文件 137.2 MB;GC 计数 GC Young=0 Conc=0 Old=0 → GC Young=0 Conc=0 Old=1
  jcmd GC.heap_dump          耗时 0.24 s;文件 137.2 MB;GC 计数 GC Young=0 Conc=0 Old=0 → GC Young=0 Conc=0 Old=1
  jcmd GC.heap_dump -all     耗时 0.49 s;文件 454.1 MB;GC 计数 GC Young=0 Conc=0 Old=0 → GC Young=0 Conc=0 Old=0

分步演示

jmap
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12,G1,-Xmx1g -Xms1g -Xmn600m;堆约 400 MB,应用在同一台机器上,其它进程不干扰
    • 没有验证:更大的堆(数 GB)上的暂停时间与文件大小是否线性放大、转储期间磁盘慢时的影响、dump 文件的 gzip 选项、用 MAT/VisualVM 打开分析(见其它篇)、不同 GC(ZGC / Parallel)下 :live 的 GC 形态、JDK 17 / 27 的差异
    京ICP备2026067502号-1京公网安备11010502063487号