JVM jmap命令的用法小结
https://www.jianshu.com/p/19ba425cc8f8 jmap -heap -dump -histo
jmap
之前已经总结过了jstack命令的用法。今天时间不太够了,没法写长篇大论,来简单看看jmap命令吧。
jmap是JVM自带的堆内存转储(heap dump)生成工具,可以用来分析某JVM进程的堆内存占用,以及所有对象的概况。其用法说明如下所示。
~ jmap -help
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
不再逐字解释了,直接上示例。
-heap:打印堆配置信息和使用概况
~ jmap -heap 3065
Attaching to process ID 3065, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.172-b11
using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 357892096 (341.3125MB)
MaxNewSize = 357892096 (341.3125MB)
OldSize = 715849728 (682.6875MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 322109440 (307.1875MB)
used = 151490152 (144.4722671508789MB)
free = 170619288 (162.7152328491211MB)
47.03064647841429% used
Eden Space:
capacity = 286326784 (273.0625MB)
used = 147538816 (140.7039794921875MB)
free = 138787968 (132.3585205078125MB)
51.52812249656672% used
From Space:
capacity = 35782656 (34.125MB)
used = 3951336 (3.7682876586914062MB)
free = 31831320 (30.356712341308594MB)
11.042601197630495% used
To Space:
capacity = 35782656 (34.125MB)
used = 0 (0.0MB)
free = 35782656 (34.125MB)
0.0% used
concurrent mark-sweep generation:
capacity = 715849728 (682.6875MB)
used = 324490944 (309.45867919921875MB)
free = 391358784 (373.22882080078125MB)
45.32947786494095% used
16612 interned Strings occupying 1535376 bytes.
在Heap Configuration一节,会输出与堆相关的JVM参数。在Heap Usage一节,会输出新生代(Eden区、Survivor From/To区)和老生代的容量、用量和空闲量。除此之外,还会输出采用的垃圾收集器,以及字符串常量池中驻留的字符串数量、大小等。关于字符串常量池,可以参见很久很久之前写的这篇文章。
-histo:生成类的实例统计直方图
~ jmap -F -histo 8766 > histo_8766.txt
Iterating over heap. This may take a while...
Heap traversal took 102.943 seconds.
~ head -30 histo_8766.txt
Attaching to process ID 8766, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.172-b11
Object Histogram:
num #instances #bytes Class description
--------------------------------------------------------------------------
1: 68784 312237944 byte[]
2: 306815 29853976 char[]
3: 32350 8154032 int[]
4: 90110 7610008 java.lang.Object[]
5: 250755 6018120 java.lang.String
6: 19090 5345200 org.apache.spark.status.TaskDataWrapper
7: 111298 3561536 java.util.HashMap$Node
8: 79859 2555488 java.util.concurrent.ConcurrentHashMap$Node
9: 102353 2456472 scala.collection.immutable.$colon$colon
10: 18024 1996520 java.lang.Class
11: 77193 1852632 java.lang.Long
12: 6853 1385888 java.util.HashMap$Node[]
13: 53685 1288440 java.util.concurrent.ConcurrentSkipListMap$Node
14: 35352 1131264 com.codahale.metrics.WeightedSnapshot$WeightedSample
15: 24500 980000 org.apache.spark.streaming.kafka010.OffsetRange
16: 39209 941016 scala.Tuple2
17: 28115 899680 scala.collection.mutable.ListBuffer
18: 3269 875352 boolean[]
19: 35097 842328 java.lang.Double
20: 1248 818688 io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueue
21: 349 757232 java.util.concurrent.ConcurrentHashMap$Node[]
22: 6330 658320 java.io.ObjectStreamClass
打印的结果有实例数、占用内存总大小和类的全限定名,并按占用内存降序排序。如果在-histo后面加上:live开关的话,表示只统计存活的对象,即在统计之前会触发一次Full GC。
特别注意,遍历堆并生成直方图的过程中,目标JVM都是stop-the-world的,所以对于较大的堆或者生产环境上的程序,要谨慎执行。如果目标JVM无响应,就加上-F参数强制执行之(同jstack),此时:live开关无效化。
-dump:生成堆转储快照文件
~ jmap -dump:live,format=b,file=dump_8766.hprof 8766
Dumping heap to /root/dump_8766.hprof ...
Heap dump file created
生成的二进制快照文件可以使用jhat、MAT、VisualVM等带有分析heap dump功能的工具查看详情,比如通过保留大小(retained size)指标来观察有哪些对象在引用大对象。
:live开关和-F参数的功能与-histo选项下相同,并且生成快照文件的过程同样会stop-the-world。
-finalizerinfo:输出等待finalize的对象数
~ jmap -finalizerinfo 3065
Attaching to process ID 3065, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.172-b11
Number of objects pending for finalization: 0
关于finalize和F-Queue的细节,应该另外写篇文章专门说说。今天就酱紫吧,民那晚安。