1. 功能简介
jmap
是 JDK
自带的工具软件,可用于生成指定 Java 进程的 Heap Dump 文件, 也可以查看堆内对象实例的统计信息、ClassLoader 的信息以及 finalizer 队列中等待被回收的对象的信息。 JDK 自带的工具都有 Java 进程所属用户的概念,需注意如果当前登录用户和进程启动用户不是同一个时,该命令无法获取到正确信息
2. 使用方式
在终端界面使用 man jmap
可以方便地获得 jmap
命令帮助文档,其命令格式如下
命令格式 | 参数说明 |
---|---|
jmap [ option ] pid | pid 为 Java 应用程序的进程号 |
jmap [ option ] executable core | executable 为产生core dump的 java可执行程序,core为打印出的core文件 |
jmap [ option ] [ server-id@] remote-hostname-or-IP | remote-hostname-or-ip 是远程 debug 服务器的名称或IP,server-id是唯一id,假如一台主机上有多个远程 debug 服务会需要区分 |
Options | 功能 |
---|---|
< no option > | 使用不带选项参数的jmap 命令将会打印目标虚拟机中加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称 |
-dump:[live,]format=b,file=< filename > | 以 hprof 二进制格式转储 Java 堆到指定 fileName 的文件中。如果指定了live 子选项,只有 Active 状态的对象会被转储,会触发 Full GC , gc log 中关键字为 Heap Dump Initiated GC ,可以使用jhat (Java堆分析工具)读取生成的 heap dump 文件 |
-finalizerinfo | 打印等待回收的对象信息 |
-heap | 打印堆的简要信息,包括使用的GC算法、堆配置信息和generation wise heap usage |
-histo[:live] | 打印堆中对象信息,包括每个Java类、对象数量、内存大小(单位:字节)、完全限定的类名。打印的虚拟机内部的类名称将会带有一个’*’前缀。如果指定了live 子选项,则只计算活动的对象,会触发 Full GC ,gc log 中的关键字为 Heap Inspection Initiated GC |
-clstats | Java 8 之后 HotSpot 虚拟机永久代取消,取代 -permstat 的参数选项,可打印元空间的类加载器的统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。另外,包含的字符串数量和大小也会被打印 |
-F | 强制模式,如果指定的 pid 没有响应,建议使用 jmap -dump 或 jmap -histo 选项,该模式下不支持live子选项 |
-J< flag > | 传递指定参数给运行 jmap 的 JVM |
3. 基本示例
3.1 -heap 选项
jmap -heap 14480
使用以上命令查看 Java 进程 14480 的堆(heap)使用情况,打印如下信息
// 开启了线程本地分配缓冲区(TLAB)
using thread-local object allocation.
// 并行 GC 收集算法,4 个线程
Parallel GC with 4 thread(s)
// 堆内存区域初始化配置
Heap Configuration:
// 对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)
MinHeapFreeRatio = 0
// 设置JVM堆最大空闲比率(default 70)
MaxHeapFreeRatio = 100
// 对应jvm启动参数-XX:MaxHeapSize= 设置JVM堆的最大大小
MaxHeapSize = 134217728 (128.0MB)
// 对应jvm启动参数-XX:NewSize= 设置JVM堆‘新生代’的默认大小
NewSize = 42991616 (41.0MB)
// 对应jvm启动参数-XX:MaxNewSize= 设置JVM堆的‘新生代’的最大大小
MaxNewSize = 44564480 (42.5MB)
// 对应jvm启动参数-XX:OldSize= 设置JVM堆的‘老年代’的大小
OldSize = 87031808 (83.0MB)
// 对应jvm启动参数-XX:NewRatio= 设置‘新生代’和‘老生代’的大小比率
NewRatio = 2
// 对应jvm启动参数-XX:SurvivorRatio= 设置年轻代中Eden区与Survivor区的大小比值
SurvivorRatio = 8
// 对应jvm启动参数-XX:MetaspaceSize= , Java 8 之后类相关信息存放在元空间(不属于堆内存),此为元空间初始化大小
MetaspaceSize = 21807104 (20.796875MB)
// 类指针压缩空间大小, 默认为1G。UseCompressedClassPointer 这个选项打开后,class信息中的指针也用 32bit
// 的 Compressed版本,而这些指针指向的空间被称作“Compressed Class Space”。如果java程序引用了太多的包,
// 有可能会造成这个空间不够用,于是会看到java.lang.OutOfMemoryError: Compressed class space 这时
// 一般调大CompreseedClassSpaceSize 就可以了,-XX:CompressedClassSpaceSize=
CompressedClassSpaceSize = 1073741824 (1024.0MB)
// 对应jvm启动参数-XX:MaxMetaspaceSize= 设置元空间最大大小
MaxMetaspaceSize = 17592186044415 MB
// G1 收集器单个 region 的大小
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
// 年轻代内存使用情况
PS Young Generation
Eden Space:
capacity = 26214400 (25.0MB)
used = 16168040 (15.419044494628906MB)
free = 10046360 (9.580955505371094MB)
61.676177978515625% used
From Space:
capacity = 524288 (0.5MB)
used = 266000 (0.2536773681640625MB)
free = 258288 (0.2463226318359375MB)
50.7354736328125% used
To Space:
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
// 年老代内存使用情况
PS Old Generation
capacity = 73400320 (70.0MB)
used = 73146256 (69.75770568847656MB)
free = 254064 (0.2422943115234375MB)
99.65386526925224% used
// 字符串常量池中的字符串信息
31347 interned Strings occupying 3713392 bytes.
3.2 -histo 选项
// 将对内存中类相关信息输入到目标文件
jmap -histo 17134 > heap.log
// 查看该文件到前10行
head heap.log
jmap -histo
命令打印堆内存中的对象数量及其所占内存的大小,通常这个列表会很大,终端界面不可能完全显示,所以最好将其输出到一个文件中,再查看这个文件即可。注意 jmap -histo:live
这个命令执行,JVM 会先触发 Full GC,然后再统计信息
num #instances #bytes class name
编号 实例数量 占用内存 类的名称
----------------------------------------------
1: 90382 8994744 [C
2: 90151 2163624 java.lang.String
3: 63510 2032320 java.util.concurrent.ConcurrentHashMap$Node
4: 13058 1451536 java.lang.Class
5: 15017 1321496 java.lang.reflect.Method
6: 7809 1158504 [B
7: 19242 1153512 [Ljava.lang.Object;
- 输出中 class name 非自定义类对照表
非自定义类 数据类型 B byte C char S short I int J long F float D double Z boolean [ 一维数组引用 L 类实例引用
3.3 -dump 选项
jmap -dump:live,format=b,file=dump 17134
这个命令执行,JVM会将整个 heap 的信息 dump 输出到指定文件,如果 heap 比较大会导致这个过程比较耗时,并且执行的过程中为了保证 dump 的信息是可靠的,JVM 会暂停程序运行。dump 文件生成后,可运行命令jhat -port 10086 dump
, 在浏览器中访问 http://localhost:10086/
即可查看详细信息