jmap.exe 是 JDK 中的一个命令行工具,全称为 JVM Memory Map,主要用于查看 Java 堆内存的使用状况。
jmap 可以生成堆的转储快照(dump文件),也可以查看堆内存中的对象实例数量、内存大小等信息。
jmap 生成的 dump 文件可以配合 jhat 工具进行分析,jhat 会启动一个 web 服务,用户可以通过浏览器查看和分析 dump 文件。
jmap 提供了多种生成堆转储文件的方式,包括在 JVM 运行时获取 dump 文件,以及在 JVM 启动时指定参数,当发生 OutOfMemoryError 时自动执行堆转储。
连接正在运行的进程:
jmap [option] <pid>
连接到核心文件:
jmap [option] <executable <core>
连接远程调试服务器:
jmap [option] [server_id@]<remote server IP or hostname>
jmap 支持如下选项:
<none> 打印与 Solaris pmap 相同的信息
-heap 打印 java 堆摘要
-histo[:live] 打印 java 对象堆的直方图;如果指定了 "live" 子选项,则只计算实时对象的数量
-clstats 打印类加载器统计数据
-finalizerinfo 打印等待最终完成的对象信息
-dump:<dump-options> 以 hprof 二进制格式转储 java 堆 dump-options:
live 仅转储实时对象;如果未指定,则转储堆中的所有对象。
format=b 二进制格式。
file=<file> 将堆转储到 <file> 文件中。
示例:jmap -dump:live,format=b,file=heap.bin <pid>
-F 强制。与 -dump:<dump-options> <pid> 或 -histo 一起使用,可在 <pid> 没有响应时强制转储堆或直方图。该模式下不支持 "live" 子选项。
-h | -help 用于打印帮助信息
-J<flag> 直接将 <flag> 传递给运行时系统。
(1)查看进程的内存映像信息,如下:
D:\share_dir\ShareDoc> jmap 21108 Attaching to process ID 21108, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.45-b02 0x0000000051ca0000 44K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\sunmscapi.dll 0x0000000051cb0000 144K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\sunec.dll 0x0000000051ce0000 52K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\management.dll 0x0000000051cf0000 140K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\instrument.dll 0x0000000051d20000 68K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\nio.dll 0x0000000051d40000 104K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\net.dll 0x0000000051d60000 88K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\zip.dll 0x0000000051d80000 164K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\java.dll 0x0000000051db0000 60K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\verify.dll 0x0000000051dc0000 8716K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\server\jvm.dll 0x0000000052650000 840K D:\ProgramFilesFree\Java\jdk1.8.0_45\jre\bin\msvcr100.dll 0x00007ff7b13c0000 220K D:\ProgramFilesFree\Java\jdk1.8.0_45\bin\java.exe ....
上面示例中,打印 Java 进程ID 为 21108 虚拟机中加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。
(2)显示 Java 堆的详细信息,如下:
D:\share_dir\ShareDoc> jmap -heap 21108 Attaching to process ID 21108, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.45-b02 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 4227858432 (4032.0MB) NewSize = 88080384 (84.0MB) MaxNewSize = 1409286144 (1344.0MB) OldSize = 176160768 (168.0MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 138936320 (132.5MB) used = 58500320 (55.790252685546875MB) free = 80436000 (76.70974731445312MB) 42.1058510834316% used From Space: capacity = 7864320 (7.5MB) used = 5242880 (5.0MB) free = 2621440 (2.5MB) 66.66666666666667% used To Space: capacity = 12058624 (11.5MB) used = 0 (0.0MB) free = 12058624 (11.5MB) 0.0% used PS Old Generation capacity = 146276352 (139.5MB) used = 25092136 (23.929725646972656MB) free = 121184216 (115.57027435302734MB) 17.15392519496248% used 19171 interned Strings occupying 1776256 bytes.
上面命令将显示 Java 进程ID 为 21108 虚拟机的信息,包括使用的垃圾回收算法、堆配置信息和各内存区域内存使用信息在内的 Java 堆的详细信息。
(3)显示堆中对象的统计信息,如下:
D:\share_dir\ShareDoc> jmap -histo:live 21108 > tmp.txt num #instances #bytes class name ---------------------------------------------- 1: 40968 4257264 [C 2: 11868 1044384 java.lang.reflect.Method 3: 40478 971472 java.lang.String 4: 8132 899808 java.lang.Class 5: 27347 875104 java.util.concurrent.ConcurrentHashMap$Node 6: 4404 567288 [B 7: 8457 429488 [Ljava.lang.Object; 8: 9451 378040 java.util.LinkedHashMap$Entry 9: 4067 329616 [Ljava.util.HashMap$Node; 10: 6008 288384 org.aspectj.weaver.reflect.ShadowMatchImpl 11: 4694 262864 java.util.LinkedHashMap 12: 7617 243744 java.util.HashMap$Node 13: 116 233536 [Ljava.util.concurrent.ConcurrentHashMap$Node; 14: 3877 212368 [I ... 3264: 1 16 sun.util.locale.provider.SPILocaleProviderAdapter 3265: 1 16 sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter 3266: 1 16 sun.util.resources.LocaleData 3267: 1 16 sun.util.resources.LocaleData$LocaleDataResourceBundleControl Total 304943 14876288
上面命令将显示堆中对象的统计信息,包括每个Java类、对象数量、内存大小(单位:字节)和完全限定的类名。指定了live子选项,因此只计算活动的对象。
(4)打印类加载器信息,如下:
D:\share_dir\ShareDoc> jmap -clstats 21108 Attaching to process ID 21108, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.45-b02 finding class loader instances ..done. computing per loader stat ..done. please wait.. computing liveness.liveness analysis may be inaccurate ... class_loader classes bytes parent_loader alive? type <bootstrap> 2442 4306147 null live <internal> 0x00000006c4b166b0 1 880 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009df8 0x000000076d218120 3 6022 0x00000006c40142e8 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c02daa38 0x00000006c4dd00d8 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009df8 0x000000076cf698f0 0 0 null dead com/sun/jmx/remote/util/OrderClassLoaders@0x00000007c053e290 0x000000076ec04ac8 3 6022 0x00000006c40142e8 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c02daa38 0x00000006c4b164b8 1 880 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009df8 ... 0x000000076e956d68 0 0 0x000000076e956930 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c02dad50 0x00000006c4de9d20 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009df8 total = 277 8342 14807542 N/A alive=1, dead=276 N/A
上面命令将打印 Java 堆内存的方法区的类加载器的智能统计信息,包括类加载器的名称、活跃度、地址、父类加载器以及加载的类的数量和大小。
(5)生成堆转储快照 dump 文件,如下:
D:\share_dir\ShareDoc> jmap -dump:format=b,file=heapdump.hprof 21108 Dumping heap to D:\share_dir\ShareDoc\heapdump.hprof ... Heap dump file created
上面命令将以二进制格式将 Java 堆转储到名为 heapdump.hprof 的文件中,可以使用 jhat 或其他堆分析工具来分析这个文件。