jmap: Java's own performance monitoring tool

Keywords: Java Apache Zookeeper jvm

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.~

Posted by vivekjain on Tue, 16 Jul 2019 16:29:21 -0700