Troubleshooting Java applications – Part 1: jmap

If you encounter abnormal behaviour in your Java application, Java offers you a set of tools to effectively identify the culprit. The first one, which I want to present, is jmap.

jmap

jmap, which is part of the JDK, is the tool of choice, if you get the impression, that you have a resource leak. With a simple command, you can create a histogram of all Java objects on the heap of your process:

jmap -histo PID

(where PID is the process ID of your Java process)

The output will look like this:

 num   #instances      #bytes  class name
----------------------------------------------
 1:       2031082   185199616  [C
 2:       2013868    64443776  java.lang.String
 3:        656635    21012320  java.util.HashMap$Entry
 4:        614312    14743488  de.christophlorenz.foo.Culprit
 5:         81443    12737392  <constMethodKlass>
 6:        123267    11564632  [Ljava.util.HashMap$Entry;
 7:         81443    11083656  <methodKlass>
...
3263:          1          16   sun.reflect.GeneratedMethodAccessor63
3264:          1          16   de.christophlorenz.foo.SomeFactory
Total    7182799   426077152

As you can see in number four, there are no less than 614312 instances of the Culprit class, consuming a little less than 15MB in total. It’s now up to you to decide, whether it’s the desired beaviour or not.

(Don’t worry about the large number of [C and [I entries, they are native character and ints, you will certainly use a lot.)

Now, as an other example, imagine, your RabbitMQ server is stressed by too many connections, maybe even blocking clients to connect, and someone has the suspicion, that your application might be running wild. With a simple jmap call, you can check your application and verify (or deny), that it is the cause:

jmap -histo 12345 | grep -i rabbitmq
 ...
 130:    14360   344640 [Lcom.rabbitmq.client.Address;
 131:    14356   344544 com.rabbitmq.client.Address
 188:     6250   100000 com.rabbitmq.client.impl.LongStringHelper$ByteArrayLongString
 212:      625    75000 com.rabbitmq.client.impl.AMQConnection$MainLoop
 226:      625    65000 com.rabbitmq.client.impl.AMQConnection
 235:      625    60000 com.rabbitmq.client.impl.ChannelN
 ...

Now, are you sure, you really need 625 connections to your RabbitMQ? No? Just go ahead and fix it 🙂

Of course, with jmap, you have many more options, like generating full heap- and thread dumps, which can later be analyzed by jvisualvm, but I’ll talk about that later.

One thought on “Troubleshooting Java applications – Part 1: jmap

  1. Pingback: jmap – so small, so powerful | The Metatechnical Blog

Leave a Reply