JDK 的 bin 目录下为 Java 开发人员提供了很多实用的小工具,很多场景下都会用到它们,比如:打包、部署、签名、调试、监控、运维等。本文介绍其中一款:
jmap (Memory Map for Java): Java 内存映像工具
功能
生成堆转储快照 (一般称为 heapdump 或 dump 文件)。
查询 finalize 执行队列、Java 堆和方法区的详细信息,如空间使用率、当前用的是哪种收集器等。
获取 Java 堆转储快照的其他方法
- XX:+HeapDumpOnOutOfMemoryError
让虚拟机在内存溢出异常出现之后自动生成堆转储快照文件。
-XX:+HeapDumpOnCtrlBreak
可以使用 [Ctrl] + [Break] 键让虚拟机生成堆转储快照文件。
Kill -3
发送进程退出信号“恐吓”一下虚拟机,也能顺利拿到堆转储快照。
Kill -3 使用示例
以 arthas 官网提供的 arthas-demo.jar 为例。
- 在本地启动 arthas-demo.jar,并将日志输出到指定文件:
1 | $ nohup java -jar arthas-demo.jar > demo.log & |
- jps 查询 LVMID (进程 ID) 为 54776:
1 | $ jps -l | grep arthas-demo.jar |
- 执行 Kill -3:
1 | $ Kill -3 54776 |
- 查看 demo.log 文件内容
命令格式
1 | jmap [ option ] vmid |
options
选项 | 作用 |
---|---|
-dump | 生成 Java 堆转储快照。格式为:-dump:[live, ]format=b,file=<filename> ,其中 live 子参数说明是否只 dump 出存活的对象 |
-finalizerinfo | 显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象。只在 Linux/Solaris 平台下有效 |
-heap | 显示 Java 堆详细信息,如使用哪种回收器、参数配置、分代状况等。只在 Linux/Solaris 平台下有效 |
-histo | (histogram) 显示堆中对象统计信息,包括类、实例数量、合计容量 |
-permstat(x) | 以 ClassLoader 为统计口径显示永久代内存状态。只在 Linux/Solaris 平台下有效 (高版本已移除) |
-F | 当虚拟机进程对 -dump 选项没有响应时,可使用这个选项强制生成dump快照。只在 Linux/Solaris 平台下有效 |
-clstats | 输出 ClassLoader 统计 |
执行样例
-dump
生成 Java 堆转储快照。格式为:-dump:[live, ]format=b,file=<filename>
,其中 live 子参数说明是否只 dump 出存活的对象。
1 | $ jmap -dump:format=b,file=resourceManager.bin 5511 |
-finalizerinfo
显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象。只在 Linux/Solaris 平台下有效。
1 | $ jmap -finalizerinfo 5511 |
-heap
显示 Java 堆详细信息,如使用哪种回收器、参数配置、分代状况等。只在 Linux/Solaris 平台下有效。
1 | $ jmap -heap 5511 |
-histo
(histogram) 显示堆中对象统计信息,包括类(class name)、实例数量(instances)、合计容量(bytes)。
1 | $ jmap -histo 5511 |
-clstats
输出 ClassLoader 统计。
1 | $ jmap -clstats 5511 |
分析堆转储快照
堆转储快照直接看看不懂,如何来分析 jmap 生成的堆转储快照?
可以用 JVM 提供的另一款小工具 - jhat,但其实这个一般会比较少用,大多数情况是用 VisualVM 或 JProfiler 等工具,因为这些工具功能更强大。