Recently a Java Web Application on which I work ran out of memory and had to be restarted. We have monitoring tools but not ones that are helpful identifying the source of a memory leak. Working for a large organization with an established bureacracy my options were quite limited. After some research the only available option was to use the “jmap” command line utility that comes with the JDK. This discussion assumes that you have access to the computer/server on which the Java application server is running.
To follow along you will need an application server preferrably with a web application deployed to the server. You will need a current version of the JDK instlled. In my setup I am running Liferay Portal on a Tomcat 7 application server using JDK 8. These instructions should work with any Java base application server. From a high level view it is a simple process.
Start your application server
Find the pid for the application server
Run jmap against the pid
As a developer I have multiple versions of the JDK installed on my workstation. The first time I ran jmap I received the following error. This was due to using Oracle JDK 8 to run the server and the OpenJDK 8 being in my path. This was easily resolved by running the jmap from the Oracle JDK installation.
Terminal window in mysecurity directory
Jmap can provide you with an overview of the heap which is useful for tuning garbage collection and a histogram listing objects memory usage from most to least. I will provide an example of the first but our focus will largely be on the second.
jmap -heap 22340
Information such as the ratios, Eden space and New Generation space can be used to tune your JVMs garbage collection. JVM tuning is outside the scope of this article. Java Performance Tuning delves into the subject quite thoroughly.
jmap -heap 22340
The “:live” part of the command only displays objects that are still being referenced. This will be more useful for diagnosing my memory leak. As we can see the objects taking up the most memory are “[C”. What is this class? It turns out this is documented in the Java API documents under Class.getName(). A copy of which is provided below.
Class.getName() type codes
Characters taking up most of the space is believable since the JVM stores Strings as character arrays in memory. This will be most useful if you take a snapshot when your application is running normally. Then when something goes wrong you will have a baseline for comparison.