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.
Pingback: jmap – so small, so powerful | The Metatechnical Blog