JDK中的jmap
是一个实用的JVM诊断工具,它可以用于生成JVM堆的快照信息,在分析Java应用程序的内存使用和排查内存泄漏问题时非常有用。下面我们以JDK8为例对jmap
工具的使用方法进行介绍。
-heap
参数用于输出JVM中堆内存的统计信息。
jmap -heap <pid>
下面是一个执行该命令的例子输出。
Attaching to process ID 25684, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.382-b05
using thread-local object allocation.
Parallel GC with 18 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 17121148928 (16328.0MB)
NewSize = 357040128 (340.5MB)
MaxNewSize = 5706874880 (5442.5MB)
OldSize = 714604544 (681.5MB)
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 = 267911168 (255.5MB)
used = 140703536 (134.1853485107422MB)
free = 127207632 (121.31465148925781MB)
52.51872740146465% used
From Space:
capacity = 44564480 (42.5MB)
used = 0 (0.0MB)
free = 44564480 (42.5MB)
0.0% used
To Space:
capacity = 44564480 (42.5MB)
used = 0 (0.0MB)
free = 44564480 (42.5MB)
0.0% used
PS Old Generation
capacity = 497025024 (474.0MB)
used = 15699920 (14.972610473632812MB)
free = 481325104 (459.0273895263672MB)
3.1587785809351927% used
15096 interned Strings occupying 1367912 bytes.
输出内容中包括了堆各分区的大小、已使用空间、空闲空间等各种信息。
-clstats
参数用于输出元数据空间中类加载的统计信息。
jmap -clstats <pid>
下面是一个执行该命令的例子输出。
Attaching to process ID 25684, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.382-b05
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> 2175 3789701 null live <internal>
0x00000003c389d588 1 1472 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000003c389b200 1 773 null dead javax/management/remote/rmi/NoCallStackClassLoader@0x00000007c00e2850
0x0000000673b193b8 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000670fe1270 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673b6beb8 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000674008190 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c0443540
0x0000000674008590 0 0 0x00000006740081d8 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c0443858
0x0000000671333020 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673b40ba0 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673d51dc0 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c0443540
0x0000000673d51fc0 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c0443858
0x0000000674002e98 0 0 0x00000003c380e140 dead com/sun/jmx/remote/util/OrderClassLoaders@0x00000007c0445eb0
0x00000003c389af90 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673b336a8 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c0443858
0x0000000673b5eca8 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000006711f3e80 1 880 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673ff7d60 0 0 0x00000003c380e140 dead com/sun/jmx/remote/util/OrderClassLoaders@0x00000007c0445eb0
0x00000003c3820920 1 1472 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000670addb08 1 1471 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673fe9fd8 0 0 0x0000000673fe9c20 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c0443858
0x0000000673b71f90 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000003c381ed28 1 1471 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000003c381f128 1 1471 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000671340998 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x000000067110cd20 1 880 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000006711e2d28 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673d6b2e0 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673fef3c8 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c0443540
0x0000000673fef5c8 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c0443858
0x00000003c389b130 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000003c380e140 3070 5136665 0x00000003c38702f0 live sun/misc/Launcher$AppClassLoader@0x00000007c000f730
0x000000067130a170 1 1472 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000003c3d1e010 0 0 0x00000003c380e140 live java/util/ResourceBundle$RBClassLoader@0x00000007c0111d60
0x00000003c3822cc0 1 1472 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x000000066fe70220 0 0 0x00000003c380e140 live org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader@0x00000007c03865f8
0x0000000673ffd8b8 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c0443540
0x0000000673ffdcb8 0 0 0x0000000673ffd900 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c0443858
0x0000000673b86570 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000003c389aec0 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000003c38207c8 1 1472 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673b31ff8 0 0 0x00000003c380e140 dead com/sun/jmx/remote/util/ClassLoaderWithRepository@0x00000007c0443008
0x000000066cb57bf8 1 1471 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000006729d52d0 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673fdff30 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c0443540
0x0000000673fe0130 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c0443858
0x0000000673b04960 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000674002e50 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c0443540
0x0000000674003250 0 0 0x0000000674002e98 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c0443858
0x0000000673fef1a8 0 0 0x00000003c380e140 dead com/sun/jmx/remote/util/ClassLoaderWithRepository@0x00000007c0443008
0x0000000673b0b268 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000006740081d8 0 0 0x00000003c380e140 dead com/sun/jmx/remote/util/OrderClassLoaders@0x00000007c0445eb0
0x00000003c381f3d8 1 1471 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000006712472f8 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673b56ce8 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673fe9c20 0 0 0x00000003c380e140 dead com/sun/jmx/remote/util/OrderClassLoaders@0x00000007c0445eb0
0x0000000673b12b50 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x000000067112d270 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673ff7d18 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c0443540
0x0000000673ff8118 0 0 0x0000000673ff7d60 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader$ClassLoaderWrapper@0x00000007c0443858
0x00000003c389b060 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000003c389b2e0 1 742 null dead javax/management/remote/rmi/NoCallStackClassLoader@0x00000007c00e2850
0x0000000673b33058 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c0443540
0x000000066dec5f80 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673d5c7b8 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673fdfd10 0 0 0x00000003c380e140 dead com/sun/jmx/remote/util/ClassLoaderWithRepository@0x00000007c0443008
0x00000003c38209f0 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000006716d7c98 1 1472 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673d51ba0 0 0 0x00000003c380e140 dead com/sun/jmx/remote/util/ClassLoaderWithRepository@0x00000007c0443008
0x000000066cb6f240 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x00000003c38702f0 11 13304 null live sun/misc/Launcher$ExtClassLoader@0x00000007c000fad8
0x00000003c381f1f8 1 1471 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000671c9c3b0 1 880 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673d63fa8 1 1471 null dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673fe9780 0 0 0x00000003c380e140 dead javax/management/remote/rmi/RMIConnectionImpl$CombinedClassLoader@0x00000007c0443540
0x000000066bf74d88 1 1472 0x00000003c380e140 dead sun/reflect/DelegatingClassLoader@0x00000007c0009e78
0x0000000673b795c8 1 1084 0x00000003c380e140 dead sun/reflect/misc/MethodUtil@0x00000007c0444cf8
0x0000000673ffd900 0 0 0x00000003c380e140 dead com/sun/jmx/remote/util/OrderClassLoaders@0x00000007c0445eb0
total = 78 5302 9003766 N/A alive=5, dead=73 N/A
-histo
参数用于输出堆中的对象统计信息,如果加上live
参数,则只统计活动对象。
jmap -histo <pid>
jmap -histo:live <pid>
这里要注意的一点是live
参数会立即触发1次FullGC,如果是线上工程应该谨慎使用,既然如此,该命令其实也可以用于在命令行手动触发1次FullGC。
下面是一个执行该命令的例子输出。
num #instances #bytes class name
----------------------------------------------
1: 6152 6746632 [B
2: 34507 3465760 [C
3: 5574 945584 [I
4: 34317 823608 java.lang.String
5: 8883 781704 java.lang.reflect.Method
6: 6567 779080 java.lang.Class
7: 13610 435520 java.util.concurrent.ConcurrentHashMap$Node
8: 6513 343640 [Ljava.lang.Object;
9: 3592 307976 [Ljava.util.HashMap$Node;
10: 7589 303560 java.util.LinkedHashMap$Entry
11: 7790 249280 java.util.HashMap$Node
12: 10774 242616 [Ljava.lang.Class;
13: 3592 201152 java.util.LinkedHashMap
14: 111 154224 [Ljava.util.concurrent.ConcurrentHashMap$Node;
15: 8398 134368 java.lang.Object
16: 3114 124560 java.lang.ref.Finalizer
17: 1476 106272 java.lang.reflect.Field
18: 1134 90720 java.lang.reflect.Constructor
19: 1623 77904 java.util.HashMap
20: 1351 75656 java.lang.invoke.MemberName
21: 1336 74816 java.util.zip.ZipFile$ZipFileInputStream
22: 1334 74704 java.util.zip.ZipFile$ZipFileInflaterInputStream
23: 1187 66472 java.lang.Class$ReflectionData
24: 1244 65408 [Ljava.lang.reflect.Method;
25: 1540 61600 java.lang.ref.SoftReference
26: 1336 57424 [Ljava.lang.String;
27: 1079 51792 org.springframework.core.ResolvableType
28: 1237 49480 java.util.TreeMap$Entry
29: 1163 46520 java.lang.invoke.MethodType
30: 1295 41440 java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
31: 1253 40096 java.util.concurrent.locks.ReentrantLock$NonfairSync
32: 1051 33632 java.util.Hashtable$Entry
33: 1363 32712 java.util.ArrayList
34: 152 29184 org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition
35: 829 26528 java.lang.invoke.DirectMethodHandle
36: 789 25248 java.lang.ref.ReferenceQueue
37: 1012 24288 sun.reflect.annotation.AnnotationInvocationHandler
我们可以使用如下命令生成堆转储文件,这里我们指定了live
参数表示只转储堆中的活动对象。
jmap -dump:live,format=b,file=heapdump.bin <pid>
我们可以在VisualVM工具中打开堆转储文件,并分析其中的内容。
生成堆转储文件时要注意,线上工程的堆内存可能比较大,生成一个巨大的转储文件可能会影响主机的性能,此外如何取回生成的堆转储文件也是个问题,因此这种方式也有一定局限性。