pmap -x pid是最有效方式,可一次性查看地址范围、rss(实际驻留内存)、权限和映射来源;不加-x则缺失rss、pss等关键列,无法判断真实内存占用与泄漏。

pmap -x PID 是最直接有效的方式,能一次性看到地址范围、实际驻留内存(RSS)、权限和映射来源——不加 -x 会漏掉关键大小和物理内存占用信息,基本等于白看。
怎么准确拿到目标进程的 PID
别用 ps aux | grep python 这种方式直接传参给 pmap,grep 自身进程常被误匹配,导致 pmap 报错 No such process:
- 精准匹配命令行:用
pgrep -f "myapp.py",它只返回数字 PID,且避开 grep 进程本身 - 查 systemd 服务:比如 nginx,用
systemctl show --property MainPID nginx.service | cut -d= -f2 - 查多实例 Java 应用:
pgrep -f "spring-boot.*prod"比pidof java更可靠,后者可能返回多个无关 PID
为什么必须用 pmap -x 而不是默认格式
默认 pmap PID 只显示十六进制起始地址、Kbytes 和 Mapping,但你看不到 RSS(真正占物理内存的页)和 PSS(按共享比例摊分的内存),无法判断是否真有泄漏:
-
pmap -x PID多出RSS和PSS列,对排查堆膨胀、匿名映射泄漏至关重要 -
RSS显著大于Kbytes?说明该段几乎全驻留,可能是缓存或未释放内存 -
Kbytes很大但RSS很小?大概率是 mmap 分配后还没 touch,属于“虚占”
从输出里快速识别关键内存段含义
每行是一个 VMA,重点盯这四类:
-
[heap]:brk 区,权限通常是rw-p;如果Kbytes和RSS持续增长,就是 malloc 泄漏的第一信号 -
[stack]或[stack:12345]:主线程或线程栈;单个超 8MB 就该查递归或大局部数组 - 带路径的共享库行(如
/lib64/libc.so.6):注意同一库出现多行,通常对应代码段(r-xp)、数据段(rw-p),设备号和 inode 一致才真是同一文件映射 -
[anon]或空 Mapping:匿名映射,常见于 JVMDirectByteBuffer、Python 的mmap.MAP_ANONYMOUS;大量碎片化小块且RSS不降,说明底层没调munmap
真正难的是把 pmap -x 输出和实际行为对应起来——比如看到一块 2GB 的 rw-p [anon],得立刻想到是不是用了 mmap(MAP_ANONYMOUS) 分配但忘了释放,而不是直接怀疑是堆泄漏。











