jZeno

pure java web development

  • Increase font size
  • Default font size
  • Decrease font size

Analyzing the heap and threads of your application

E-mail Print PDF

Besides the built-in monitoring options of jZeno, Java will allow you to create heap and thread dumps of your application. These can then be analyzed offline. The procedure to do this is described below.

Making Heap Dumps

Java 6 allows developers to dump the entire contents of a JVM's heap to a file in a binary (HPROF) format. By default you can take heap dumps of applications on your own machine. In order to do so, you should first start you application, and secondly start the JDK's jconsole application. This application will at startup show you a list of running JVMs and allow you to attach to one of these by selecting it :

 

jconsolenewconnection.jpg

 

 

It this screenshot you can see that a JVM running winstone (and the jZeno tutorial) is found on the system. Double-click it to connect to it :

jconsoleconnected.jpg 

After this you can perform a heap dump by selecting the MBeans tab. Inside of this tab, select (in the tree on the left) the option com.sun.management - Operations - dumpHeap. This will give a a form that allows you to invoke this operation :

jconsoledumpheap.jpg

Now fill in the two fields p0 (this is the full filename of the target dump file - use extension .hprof), and leave p1 set to true (this tells the JVM to only dump referenced objects, and no garbage). Then click on the dumpHeap button. Depending of the size of your heap this may take a couple of seconds. Eventually jconsole will respond by telling you that the method was invoked correctly.

It is also possible to allow remote JMX connections to your application, and generate heap dumps this way.In order to do this you must add a couple of options when starting your JVM. For more details lookup the JVM docs about adding a JMX interfaces. For an example:

-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=9321

You must then, on jconsole's connect screen use the option Remote Process to connect to the required JVM.

Heap Analysis

After you've obtained a heap dump from your running application, you need a tool to analyze this binary heap dump. We highly recommend the Eclipse Memory Analyzer . This is a desktop application that is based on Eclipse's RCP platform. It will analyze the heap dump for you, write out disk-based indexes on the heap, and then give you a user interface to rapidly search and analyze the content of the heap dump. Once the heap dump has been loaded the first time, all the necessary indexes are retained, so opening a heap dump a second time is instant.

So let's go ahead and load a heap dump (The examples below are taken from a production environment - so it's not the heap dump taken above). Start up the memory analyzer, and select File - Open Snapshot, then select the heap dump file (*.hprof). At this point MAT will parse your file :

matparsing.jpg

After some time (for large heap dumps this can be a considerable amount of time - think several minutes) you will be presented with details of your heap dump :

matparsed.jpg  

You are presented with a list of classes, the number of objects in the heap for this type, the amount of bytes taken by these objects, and an empty column that can be made to show the retained heap size. The retained heap size is the number of bytes held on the heap from this and only this object type. To calculate the retained heap size right click in one or more types and select Calculate Precise Retained Size :

matmenuretainedsize.jpg

You can also use regular expressions to seelect the desired type from the (often very long) list of classes. For example I may be interested in the HTTP session objects of my web server (in this case jetty) :

matretainedsize.jpg

In the example above I've selected the jetty Session class. As you can see in this heap dump there are 66 user sessions on the java heap. I've calculated the precise retained size of those 66 sessions, and you can see that the user sessions are on average about 728 Kb. We may also want to look at the individual session objects. You can do this by right clicking the desired type and selecting Show Objects - with outgoing references. This results in a new tab inside of MAT :

  matmenuobject.jpg

matobjects.jpg  

You can then use the tree structure on each of the individual object to drill down into any of the variables and referenced objects from here. For example, the session object will contain the current screen object, which will have a layout object, and some other child components :

  matdrilldown.jpg

Other classes you may want to analyze are :

  • net.sf.jzeno.util.DomainCache : This object references all read-only swizzled object in the application
  • net.sf.ehcache.Cache : Instances of this represent individual cache regions inside EHCache. By default jZeno uses EHCache as a hibernate 2nd level cache.
  • net.sf.jzeno.util.FastFactory : This factory contains precreated objects, that are not in use by the application.
  • your business cache class.

Making Thread Dumps

A different, and informative view of your application are thread dumps. Especially if you are experiencing locking problems, but also to just keep an eye on the amount and type of threads, etc... The tool we recommend for this is TDA. This tool is both a standalone analyzer, that allows you to analyze thread dumps offline, as well as a plugin for your JDK's jconsole tool. The plugin allows you to take full snapshots of your JVM's thread state. This includes the full stack traces, as well as information about which java monitors a thread has taken, or is waiting for.

In order to start jconsole with this new plugin, you must tell it where to find TDA on the command line when you launch jconsole :

$ jconsole -pluginpath [tda installation location]/tda.jar 

You will notice that jconsole will now have an extra tab called Thread Dumps :

tdajconsolerequest.jpg 

The only option here is to click the Request Thread Dump link. This will result in a thread dump being taken :

tdajconsolerequested.jpg

At this moment it is possible to analyze this thread dump inside of jconsole's tda plugin, be more interesting is to save this dump to disk, and analyze it offline. In order to save the thread dump, select the item Dump No. 1, right-click on it and select Save Logfile. Save the thread dump with extension .tda. After this you can start close the jconsol, and start TDA in stand-alone mode. The very same tda.jar you just specified as a plugin to jconsole also containsthe standalone application, which can be launched by issuing java -jar tda.jar on the command line :

tda.jpg

You are then presented with a desktop application. Open your previous thread dump via File -  Open.Then select the item Dump No.1 - Thread, and look at the top-right pane to see a list of threads. Select one of these threads to inspect the stack trace, and information about monitors it has taken, or is waiting on.

Thread Analysis

In order to analyze the .tda file it is sometimes handier to scan through the text file with a good text editor. This will allow you to look for threads waiting on a certain monitor, and then to directly find the thread that has locked this same monitor. Just take a good look at the text file's layout, and you'll see it's a very simple format.