JDK命令-jmap

最后更新:2020-04-24

jmap是JDK自带的工具软件,主要用于打印指定Java进程(或核心文件、远程调试服务器)的共享对象内存映射或堆内存细节。可以使用jmap生成Heap Dump。

什么是堆Dump

堆Dump是反应Java堆使用情况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等。 一般,在内存不足、GC异常等情况下,我们就会怀疑有内存泄露。这个时候我们就可以制作堆Dump来查看具体情况。分析原因。

	Usage:
	    jmap [option] <pid>
	        (to connect to running process)
	    jmap [option] <executable <core>
	        (to connect to a core file)
	    jmap [option] [server_id@]<remote server IP or hostname>
	        (to connect to remote debug server)
	
	where <option> is one of:
	    <none>               to print same info as Solaris pmap
	    -heap                to print java heap summary
	    -histo[:live]        to print histogram of java object heap; if the "live"
	                         suboption is specified, only count live objects
	    -clstats             to print class loader statistics
	    -finalizerinfo       to print information on objects awaiting finalization
	    -dump:<dump-options> to dump java heap in hprof binary format
	                         dump-options:
	                           live         dump only live objects; if not specified,
	                                        all objects in the heap are dumped.
	                           format=b     binary format
	                           file=<file>  dump heap to <file>
	                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
	    -F                   force. Use with -dump:<dump-options> <pid> or -histo
	                         to force a heap dump or histogram when <pid> does not
	                         respond. The "live" suboption is not supported
	                         in this mode.
	    -h | -help           to print this help message
	    -J<flag>             to pass <flag> directly to the runtime system

参数:

option 选项参数是互斥的(不可同时使用)。想要使用选项参数,直接跟在命令名称后即可。
pid 需要打印配置信息的进程ID。该进程必须是一个Java进程。想要获取运行的Java进程列表,你可以使用jps。
executable 产生核心dump的Java可执行文件。
core 需要打印配置信息的核心文件。
remote-hostname-or-IP 远程调试服务器的(请查看jsadebugd)主机名或IP地址。
server-id 可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器。

选项

<no option> 如果使用不带选项参数的jmap打印共享对象映射,将会打印目标虚拟机中加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。这与Solaris的pmap工具比较相似。

-dump:[live,]format=b,file=<filename> 以hprof二进制格式转储Java堆到指定filename的文件中。live子选项是可选的。如果指定了live子选项,堆中只有活动的对象会被转储。想要浏览heap dump,你可以使用jhat(Java堆分析工具)读取生成的文件。

-finalizerinfo 打印等待终结的对象信息。

-heap 打印一个堆的摘要信息,包括使用的GC算法、堆配置信息和generation wise heap usage。

-histo[:live] 打印堆的柱状图。其中包括每个Java类、对象数量、内存大小(单位:字节)、完全限定的类名。打印的虚拟机内部的类名称将会带有一个’*’前缀。如果指定了live子选项,则只计算活动的对象。

-permstat 打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印。

-F 强制模式。如果指定的pid没有响应,请使用jmap -dump或jmap -histo选项。此模式下,不支持live子选项。

-J<flag> 指定传递给运行jmap的JVM的参数

jmap -heap 2730

	Attaching to process ID 2730, please wait...
	Debugger attached successfully.
	Server compiler detected.
	JVM version is 25.20-b23
	
	using thread-local object allocation.
	Parallel GC with 4 thread(s) //GC 方式
	
	Heap Configuration: //堆内存初始化配置
	   MinHeapFreeRatio         = 0 //对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)
	   MaxHeapFreeRatio         = 100 //对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70)
	   MaxHeapSize              = 4167041024 (3974.0MB)  //对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小
	   NewSize                  = 87031808 (83.0MB) //对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小
	   MaxNewSize               = 1388838912 (1324.5MB) //对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
	   OldSize                  = 175112192 (167.0MB) //对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老生代’的大小
	   NewRatio                 = 2 //对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
	   SurvivorRatio            = 8 //对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值 
	   MetaspaceSize            = 21807104 (20.796875MB) 
	   CompressedClassSpaceSize = 1073741824 (1024.0MB)
	   MaxMetaspaceSize         = 17592186044415 MB
	   G1HeapRegionSize         = 0 (0.0MB)
	
	Heap Usage: //堆内存使用情况
	PS Young Generation
	Eden Space: //Eden区内存分布
	   capacity = 400556032 (382.0MB) //Eden区总容量
	   used     = 347517088 (331.4181213378906MB) //Eden区已使用
	   free     = 53038944 (50.581878662109375MB) //Eden区剩余容量
	   86.7586705073012% used //Eden区使用比率
	From Space: //其中一个Survivor区的内存分布
	   capacity = 49807360 (47.5MB)
	   used     = 42420016 (40.45487976074219MB)
	   free     = 7387344 (7.0451202392578125MB)
	   85.16816791735198% used 
	To Space: //另一个Survivor区的内存分布
	   capacity = 65011712 (62.0MB)
	   used     = 0 (0.0MB)
	   free     = 65011712 (62.0MB)
	   0.0% used
	PS Old Generation //当前的Old区内存分布
	   capacity = 225443840 (215.0MB)
	   used     = 144160328 (137.48200225830078MB)
	   free     = 81283512 (77.51799774169922MB)
	   63.945117329442226% used
	
	9478 interned Strings occupying 847800 bytes.

jmap -histo 2730

查看堆内存(histogram)中的对象数量及大小

jmap -histo:live 这个命令执行,JVM会先触发gc,然后再统计信息。

找到最耗内存对象

	$ jmap -histo:live 4420 | more
	
	 num     #instances         #bytes  class name
	----------------------------------------------
	   1:        190946       32397944  [C
	   2:          4484        8992432  [B
	   3:         60531        5810976  java.util.jar.JarFile$JarFileEntry
	   4:        188583        4525992  java.lang.String
	   5:        129012        4128384  java.util.HashMap$Node
	   6:         30239        2661032  java.lang.reflect.Method
	   7:         16534        2338104  [Ljava.util.HashMap$Node;
	   8:         43702        1398464  java.util.concurrent.ConcurrentHashMap$Node
	   9:         25462        1393696  [Ljava.lang.Object;
	  10:         12469        1293568  java.lang.Class
	  11:         18321         732840  java.util.LinkedHashMap$Entry
	  12:          9875         632000  java.net.URL

jmap -dump:format=b,file=heapdump 2730

将内存使用的详细情况输出到文件

Dumping heap to /root/heapdump ...
Heap dump file created

然后用jhat命令可以参看 jhat -port 5000 heapdump 在浏览器中访问:http://localhost:5000/查看详细信息

这个命令执行,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用。

	jhat -port 5000 heapdump 
	Reading from heapdump...
	Dump file created Mon Sep 26 17:06:11 CST 2016
	Snapshot read, resolving...
	Resolving 4681546 objects...
	Chasing references, expect 936 dots........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
	Eliminating duplicate references........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
	Snapshot resolved.
	Started HTTP server on port 5000
	Server is ready.

1.如果程序内存不足或者频繁GC,很有可能存在内存泄露情况,这时候就要借助Java堆Dump查看对象的情况。

2.要制作堆Dump可以直接使用jvm自带的jmap命令

3.可以先使用jmap -heap命令查看堆的使用情况,看一下各个堆空间的占用情况。

4.使用jmap -histo:[live]查看堆内存中的对象的情况。如果有大量对象在持续被引用,并没有被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉。

5.也可以使用 jmap -dump:format=b,file=命令将堆信息保存到一个文件中,再借助jhat命令查看详细内容

6.在内存出现泄露、溢出或者其它前提条件下,建议多dump几次内存,把内存文件进行编号归档,便于后续内存整理分析。

示例:

应用刚启动时:

	[root]# jmap -heap 18298
	Attaching to process ID 18298, please wait...
	Debugger attached successfully.
	Server compiler detected.
	JVM version is 25.20-b23
	
	using thread-local object allocation.
	Parallel GC with 4 thread(s)
	
	Heap Configuration:
	   MinHeapFreeRatio         = 0
	   MaxHeapFreeRatio         = 100
	   MaxHeapSize              = 104857600 (100.0MB)
	   NewSize                  = 52428800 (50.0MB)
	   MaxNewSize               = 52428800 (50.0MB)
	   OldSize                  = 52428800 (50.0MB)
	   NewRatio                 = 1
	   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 = 31981568 (30.5MB)
	   used     = 12845048 (12.249992370605469MB)
	   free     = 19136520 (18.25000762939453MB)
	   40.16390941182121% used
	From Space:
	   capacity = 10485760 (10.0MB)
	   used     = 1634392 (1.5586776733398438MB)
	   free     = 8851368 (8.441322326660156MB)
	   15.586776733398438% used
	To Space:
	   capacity = 9961472 (9.5MB)
	   used     = 0 (0.0MB)
	   free     = 9961472 (9.5MB)
	   0.0% used
	PS Old Generation
	   capacity = 52428800 (50.0MB)
	   used     = 7901552 (7.5355072021484375MB)
	   free     = 44527248 (42.46449279785156MB)
	   15.071014404296875% used
	
	9369 interned Strings occupying 805784 bytes.

隔一段时间之后,已经执行了254次YONG GC

	 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
	512.0  512.0   0.0   224.0  50176.0  49145.4   51200.0    11315.0   30848.0 29593.4 3712.0 3458.7    251    0.559   1      0.049    0.608
	512.0  512.0  256.0   0.0   50176.0  14884.8   51200.0    11323.0   30848.0 29593.4 3712.0 3458.7    252    0.561   1      0.049    0.610
	512.0  512.0  256.0   0.0   50176.0  29782.1   51200.0    11323.0   30848.0 29593.4 3712.0 3458.7    252    0.561   1      0.049    0.610
	512.0  512.0  256.0   0.0   50176.0  44732.8   51200.0    11323.0   30848.0 29593.4 3712.0 3458.7    252    0.561   1      0.049    0.610
	512.0  512.0   0.0   256.0  50176.0  10043.6   51200.0    11323.0   30848.0 29593.4 3712.0 3458.7    253    0.563   1      0.049    0.611
	512.0  512.0   0.0   256.0  50176.0  25095.5   51200.0    11323.0   30848.0 29593.4 3712.0 3458.7    253    0.563   1      0.049    0.611
	512.0  512.0   0.0   256.0  50176.0  40201.4   51200.0    11323.0   30848.0 29593.4 3712.0 3458.7    253    0.563   1      0.049    0.611
	512.0  512.0  256.0   0.0   50176.0   6033.2   51200.0    11323.0   30848.0 29593.4 3712.0 3458.7    254    0.565   1      0.049    0.613
	512.0  512.0  256.0   0.0   50176.0  21144.4   51200.0    11323.0   30848.0 29593.4 3712.0 3458.7    254    0.565   1      0.049    0.613
	512.0  512.0  256.0   0.0   50176.0  36276.1   51200.0    11323.0   30848.0 29593.4 3712.0 3458.7    254    0.565   1      0.049    0.613

在查看堆的详情

	[root]# jmap -heap 18298
	Attaching to process ID 18298, please wait...
	Debugger attached successfully.
	Server compiler detected.
	JVM version is 25.20-b23
	
	using thread-local object allocation.
	Parallel GC with 4 thread(s)
	
	Heap Configuration:
	   MinHeapFreeRatio         = 0
	   MaxHeapFreeRatio         = 100
	   MaxHeapSize              = 104857600 (100.0MB)
	   NewSize                  = 52428800 (50.0MB)
	   MaxNewSize               = 52428800 (50.0MB)
	   OldSize                  = 52428800 (50.0MB)
	   NewRatio                 = 1
	   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 = 51380224 (49.0MB)
	   used     = 16426712 (15.665733337402344MB)
	   free     = 34953512 (33.334266662597656MB)
	   31.9708843620456% used
	From Space:
	   capacity = 524288 (0.5MB)
	   used     = 327680 (0.3125MB)
	   free     = 196608 (0.1875MB)
	   62.5% used
	To Space:
	   capacity = 524288 (0.5MB)
	   used     = 0 (0.0MB)
	   free     = 524288 (0.5MB)
	   0.0% used
	PS Old Generation
	   capacity = 52428800 (50.0MB)
	   used     = 11455528 (10.924842834472656MB)
	   free     = 40973272 (39.075157165527344MB)
	   21.849685668945312% used
	
	10131 interned Strings occupying 895216 bytes.

运行很长一段时间之后

	[root ~]# jmap -heap 18298
	Attaching to process ID 18298, please wait...
	Debugger attached successfully.
	Server compiler detected.
	JVM version is 25.20-b23
	
	using thread-local object allocation.
	Parallel GC with 4 thread(s)
	
	Heap Configuration:
	   MinHeapFreeRatio         = 0
	   MaxHeapFreeRatio         = 100
	   MaxHeapSize              = 104857600 (100.0MB)
	   NewSize                  = 52428800 (50.0MB)
	   MaxNewSize               = 52428800 (50.0MB)
	   OldSize                  = 52428800 (50.0MB)
	   NewRatio                 = 1
	   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 = 51380224 (49.0MB)
	   used     = 31754656 (30.283599853515625MB)
	   free     = 19625568 (18.716400146484375MB)
	   61.803265007174744% used
	From Space:
	   capacity = 524288 (0.5MB)
	   used     = 229376 (0.21875MB)
	   free     = 294912 (0.28125MB)
	   43.75% used
	To Space:
	   capacity = 524288 (0.5MB)
	   used     = 0 (0.0MB)
	   free     = 524288 (0.5MB)
	   0.0% used
	PS Old Generation
	   capacity = 52428800 (50.0MB)
	   used     = 50564824 (48.222373962402344MB)
	   free     = 1863976 (1.7776260375976562MB)
	   96.44474792480469% used
	
	10994 interned Strings occupying 994856 bytes.

触发FULL GC

	 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT 
	512.0  512.0  192.0   0.0   50176.0  11012.5   51200.0    49451.7   32512.0 30929.3 3840.0 3587.1  27354   58.205   1      0.049   58.253
	512.0  512.0  192.0   0.0   50176.0  26107.9   51200.0    49451.7   32512.0 30929.3 3840.0 3587.1  27354   58.205   1      0.049   58.253
	512.0  512.0  192.0   0.0   50176.0  41136.6   51200.0    49451.7   32512.0 30929.3 3840.0 3587.1  27354   58.205   1      0.049   58.253
	512.0  512.0   0.0   224.0  50176.0   6932.6   51200.0    49451.7   32512.0 30929.3 3840.0 3587.1  27355   58.207   1      0.049   58.255
	512.0  512.0   0.0   224.0  50176.0  21866.4   51200.0    49451.7   32512.0 30929.3 3840.0 3587.1  27355   58.207   1      0.049   58.255
	512.0  512.0   0.0   224.0  50176.0  36832.2   51200.0    49451.7   32512.0 30929.3 3840.0 3587.1  27355   58.207   1      0.049   58.255
	512.0  512.0  224.0   0.0   50176.0   2021.9   51200.0    49451.7   32512.0 30929.3 3840.0 3587.1  27356   58.209   1      0.049   58.258
	512.0  512.0  224.0   0.0   50176.0  17076.9   51200.0    49451.7   32512.0 30929.3 3840.0 3587.1  27356   58.209   1      0.049   58.258
	512.0  512.0   0.0    0.0   50176.0  16072.8   51200.0     8972.7   32512.0 30842.7 3840.0 3574.3  27357   58.211   2      0.138   58.349
	512.0  512.0   0.0    0.0   50176.0  31106.8   51200.0     8972.7   32512.0 30842.7 3840.0 3574.3  27357   58.211   2      0.138   58.349
	512.0  512.0   0.0    0.0   50176.0  46210.0   51200.0     8972.7   32512.0 30842.7 3840.0 3574.3  27357   58.211   2      0.138   58.349

FULL GC后的堆

	[root ~]# jmap -heap 18298
	Attaching to process ID 18298, please wait...
	Debugger attached successfully.
	Server compiler detected.
	JVM version is 25.20-b23
	
	using thread-local object allocation.
	Parallel GC with 4 thread(s)
	
	Heap Configuration:
	   MinHeapFreeRatio         = 0
	   MaxHeapFreeRatio         = 100
	   MaxHeapSize              = 104857600 (100.0MB)
	   NewSize                  = 52428800 (50.0MB)
	   MaxNewSize               = 52428800 (50.0MB)
	   OldSize                  = 52428800 (50.0MB)
	   NewRatio                 = 1
	   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 = 51380224 (49.0MB)
	   used     = 42154552 (40.20171356201172MB)
	   free     = 9225672 (8.798286437988281MB)
	   82.04431339186065% used
	From Space:
	   capacity = 524288 (0.5MB)
	   used     = 229376 (0.21875MB)
	   free     = 294912 (0.28125MB)
	   43.75% used
	To Space:
	   capacity = 524288 (0.5MB)
	   used     = 0 (0.0MB)
	   free     = 524288 (0.5MB)
	   0.0% used
	PS Old Generation
	   capacity = 52428800 (50.0MB)
	   used     = 9188088 (8.762443542480469MB)
	   free     = 43240712 (41.23755645751953MB)
	   17.524887084960938% used
	
	10302 interned Strings occupying 946472 bytes.

Edgar

Edgar
一个略懂Java的小菜比