This article continues with the introduction of Java's own performance monitoring tools. This article uses jmap tools to play with them.~
jmap (Java Memory Map) command can generate heap snapshots and object statistics of Java applications, analyze the generated heap snapshots, analyze the memory occupied by objects in the heap, check large objects, etc.~
First use jmap-help to look at the basic syntax of the jmap command and the description of option s~
[root@dev18 ~]# 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 -permstat to print permanent generation 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 [root@dev18 ~]#
jmap basic grammar:
jmap [option] <pid>
Jmap needs pid, so it needs to be used in conjunction with jps, that is, first use JPS to obtain PID information, and then use jmap to process it.~
[root@dev18 ~]# jps -l 1656 org.elasticsearch.bootstrap.Elasticsearch 12905 org.apache.zookeeper.server.quorum.QuorumPeerMain 4308 /srv/activemq/apache-activemq-5.14.3//bin/activemq.jar 27265 sun.tools.jps.Jps [root@dev18 ~]#
Next, this article uses Zookeeper's service process as an example, and its pid is 1295.
Use jmap-heap 12905 to print java heap, such as
[root@dev18 ~]# jmap -heap 12905 Attaching to process ID 12905, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.71-b01 using thread-local object allocation. Parallel GC with 2 thread(s) Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 1004535808 (958.0MB) NewSize = 1310720 (1.25MB) MaxNewSize = 17592186044415 MB OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 21757952 (20.75MB) MaxPermSize = 85983232 (82.0MB) G1HeapRegionSize = 0 (0.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 15204352 (14.5MB) used = 12229848 (11.663291931152344MB) free = 2974504 (2.8367080688476562MB) 80.43649607691272% used From Space: capacity = 524288 (0.5MB) used = 32768 (0.03125MB) free = 491520 (0.46875MB) 6.25% used To Space: capacity = 524288 (0.5MB) used = 0 (0.0MB) free = 524288 (0.5MB) 0.0% used PS Old Generation capacity = 41418752 (39.5MB) used = 3584192 (3.41815185546875MB) free = 37834560 (36.08184814453125MB) 8.65354900118671% used PS Perm Generation capacity = 22020096 (21.0MB) used = 8938800 (8.524703979492188MB) free = 13081296 (12.475296020507812MB) 40.59382847377232% used 2776 interned Strings occupying 230000 bytes. [root@dev18 ~]#
Use jmap-history to print the histogram of jvm heap. Its output information includes class name, number of objects and occupancy of objects.
The following example uses jmap to generate object statistics (in the form of histograms) for Java programs pid 1295, and outputs the generated statistics to 12905.histo files in the time/usr/local directory, such as:
[root@dev18 ~]# jmap -histo 12905 >/usr/local/12905.histo
Open the 12905.histo file to view detailed information such as:
[root@dev18 ~]# vim /usr/local/12905.histo
num #instances #bytes class name ---------------------------------------------- 1: 30204 5384536 [B 2: 17521 2252160 <methodKlass> 3: 17521 2186552 <constMethodKlass> 4: 1515 1644272 <constantPoolKlass> 5: 39568 1582720 java.util.HashMap$KeyIterator 6: 10809 1457680 [C 7: 1515 1040840 <instanceKlassKlass> 8: 1368 1032128 <constantPoolCacheKlass> 9: 40162 919944 [Ljava.lang.Object; 10: 36461 875064 java.util.ArrayList 11: 35427 850248 java.lang.Long 12: 15953 765744 java.nio.HeapByteBuffer 13: 5384 387648 org.apache.zookeeper.server.Request 14: 11669 373408 java.util.HashMap$Entry 15: 3771 301296 [Ljava.util.HashMap$Entry; 16: 612 296376 [I 17: 5687 272976 java.util.HashMap 18: 3805 254448 [S 19: 7029 224928 java.util.concurrent.locks.AbstractQueuedSynchronizer$Node 20: 453 203136 <methodDataKlass> 21: 7138 171312 java.util.concurrent.LinkedBlockingQueue$Node 22: 7008 168192 java.lang.String 23: 1671 161696 java.lang.Class 24: 2507 133624 [[I 25: 5223 125352 java.util.Collections$UnmodifiableRandomAccessList 26: 3513 112416 java.io.DataInputStream 27: 3513 112416 java.io.DataOutputStream 28: 3511 112352 org.apache.zookeeper.proto.ReplyHeader 29: 1872 89856 org.apache.zookeeper.txn.TxnHeader 30: 5486 87776 java.util.HashSet 31: 3513 84312 org.apache.jute.BinaryOutputArchive 32: 3512 84288 java.io.ByteArrayOutputStream 33: 139 75616 <objArrayKlassKlass> 34: 1506 72288 org.apache.zookeeper.KeeperException$NodeExistsException 35: 1871 59872 org.apache.zookeeper.server.quorum.QuorumPacket 36: 3561 56976 java.util.HashMap$KeySet 37: 3513 56208 org.apache.zookeeper.server.ByteBufferInputStream 38: 3513 56208 org.apache.jute.BinaryInputArchive 39: 3512 56192 org.apache.zookeeper.server.SessionTrackerImpl$SessionSet 40: 1873 44952 java.util.LinkedList$Node 41: 1871 44904 org.apache.zookeeper.server.quorum.Leader$Proposal 42: 516 41280 java.lang.reflect.Method 43: 1045 33440 java.util.concurrent.ConcurrentHashMap$HashEntry 44: 1694 27104 java.lang.Object 45: 1506 24096 org.apache.zookeeper.txn.ErrorTxn 46: 106 16960 org.apache.zookeeper.server.NIOServerCnxn 47: 426 13632 java.util.concurrent.locks.ReentrantLock$NonfairSync 48: 230 12704 [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;
# instances, #bytes, and class name columns illustrate:
Instances column: Indicates how many instances of the current class are there. Bytes column: Describes how many bytes are occupied by instances of the current class Classname column: Represents the name of the current class. Classname interprets: B stands for byte C stands for char D stands for double F stands for float I stands for int J stands for long Z stands for boolean There is [representing an array, [I is equivalent to int [] Objects are represented by [L + class names
You can also use jmap-histo 12905 to view without generating files, because there are many contents, you can use the addition of | more to qualify.~
[root@dev18 ~]# jmap -histo 12905 | more num #instances #bytes class name ---------------------------------------------- 1: 30330 5407864 [B 2: 17521 2252160 <methodKlass> 3: 17521 2186552 <constMethodKlass> 4: 1515 1644272 <constantPoolKlass> 5: 39770 1590800 java.util.HashMap$KeyIterator 6: 10827 1460848 [C 7: 1515 1040840 <instanceKlassKlass> 8: 1368 1032128 <constantPoolCacheKlass> 9: 40346 923032 [Ljava.lang.Object; 10: 36645 879480 java.util.ArrayList 11: 35608 854592 java.lang.Long 12: 16025 769200 java.nio.HeapByteBuffer 13: 5402 388944 org.apache.zookeeper.server.Request 14: 11723 375136 java.util.HashMap$Entry 15: 613 357464 [I 16: 3789 302736 [Ljava.util.HashMap$Entry; 17: 5705 273840 java.util.HashMap 18: 3805 254448 [S 19: 7065 226080 java.util.concurrent.locks.AbstractQueuedSynchronizer$Node 20: 453 203136 <methodDataKlass> 21: 7174 172176 java.util.concurrent.LinkedBlockingQueue$Node 22: 7008 168192 java.lang.String 23: 1671 161696 java.lang.Class 24: 2507 133624 [[I 25: 5241 125784 java.util.Collections$UnmodifiableRandomAccessList 26: 3531 112992 java.io.DataInputStream 27: 3531 112992 java.io.DataOutputStream 28: 3529 112928 org.apache.zookeeper.proto.ReplyHeader 29: 1872 89856 org.apache.zookeeper.txn.TxnHeader 30: 5504 88064 java.util.HashSet 31: 3531 84744 org.apache.jute.BinaryOutputArchive 32: 3530 84720 java.io.ByteArrayOutputStream 33: 139 75616 <objArrayKlassKlass> 34: 1506 72288 org.apache.zookeeper.KeeperException$NodeExistsException 35: 1871 59872 org.apache.zookeeper.server.quorum.QuorumPacket 36: 3579 57264 java.util.HashMap$KeySet 37: 3531 56496 org.apache.zookeeper.server.ByteBufferInputStream 38: 3531 56496 org.apache.jute.BinaryInputArchive 39: 3530 56480 org.apache.zookeeper.server.SessionTrackerImpl$SessionSet 40: 1873 44952 java.util.LinkedList$Node 41: 1871 44904 org.apache.zookeeper.server.quorum.Leader$Proposal 42: 516 41280 java.lang.reflect.Method 43: 1045 33440 java.util.concurrent.ConcurrentHashMap$HashEntry 44: 1694 27104 java.lang.Object 45: 1506 24096 org.apache.zookeeper.txn.ErrorTxn 46: 106 16960 org.apache.zookeeper.server.NIOServerCnxn 47: 426 13632 java.util.concurrent.locks.ReentrantLock$NonfairSync 48: 230 12704 [Ljava.util.concurrent.ConcurrentHashMap$HashEntry; 49: 308 12320 java.lang.ref.SoftReference
Print permanent generation heap using jmap-permstat 12905
[root@dev18 ~]# jmap -permstat 12905 Attaching to process ID 12905, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.71-b01 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> 1267 7343336 null live <internal> 0x00000000c4292130 1 3048 null dead sun/reflect/DelegatingClassLoader@0x00000000bf04ffc8 0x00000000c420b210 0 0 null dead sun/misc/Launcher$ExtClassLoader@0x00000000bf1c0120 0x00000000c4292170 1 1888 null dead sun/reflect/DelegatingClassLoader@0x00000000bf04ffc8 0x00000000c42921b0 1 1888 null dead sun/reflect/DelegatingClassLoader@0x00000000bf04ffc8 0x00000000c4292358 2 32144 null dead javax/management/remote/rmi/NoCallStackClassLoader@0x00000000bf546b68 0x00000000c42921f0 1 1888 null dead sun/reflect/DelegatingClassLoader@0x00000000bf04ffc8 0x00000000c420b1c0 401 2657256 0x00000000c420b210 dead sun/misc/Launcher$AppClassLoader@0x00000000bf21a9c8 0x00000000c42920e0 4 13776 null dead javax/management/remote/rmi/NoCallStackClassLoader@0x00000000bf546b68 0x00000000c4292318 1 3048 null dead sun/reflect/DelegatingClassLoader@0x00000000bf04ffc8 0x00000000c42922d8 1 1888 null dead sun/reflect/DelegatingClassLoader@0x00000000bf04ffc8 0x00000000c4292298 1 3048 null dead sun/reflect/DelegatingClassLoader@0x00000000bf04ffc8 0x00000000c4312bc8 0 0 0x00000000c420b1c0 dead java/util/ResourceBundle$RBClassLoader@0x00000000bf6dce70 0x00000000c4292258 1 3056 null dead sun/reflect/DelegatingClassLoader@0x00000000bf04ffc8 total = 14 1682 10066264 N/A alive=1, dead=13 N/A [root@dev18 ~]#
jmap also has the ability to manually generate the heap snapshot file for the specified program using the-dump option~
Such as:
jmap -dump:format=b,file=/usr/local/12905.hprof 12905
This example generates a binary dump file for a program pid 1295, which is placed in the / usr/local directory.
The name is 1295. hprof~
[root@dev18 ~]# jmap -dump:format=b,file=/usr/local/12905.hprof 12905 Dumping heap to /usr/local/12905.hprof ... Heap dump file created [root@dev18 ~]#
For this dump file, you can use JDK's own jhat (Java Heap Analysis Tool) gadget to view it. You can display the paired objects in html form, including the number and size of objects, and support the Object Query Language (OQL). jhat will be introduced in the next article.~