The Art of Java Application Performance Analysis and Tuning – Part 4

This is the fourth article in the series of articles exploring the tools and techniques for analyzing, monitoring, and improving the performance of Java applications.

The Art of Java Application Performance Analysis and Tuning-Part 1                                      The Art of Java Application Performance Analysis and Tuning-Part 2                                     The Art of Java Application  Performance Analysis and Tuning-Part 3

The Art of Java Application  Performance Analysis and Tuning-Part 5                                          The Art of Java Application  Performance Analysis and Tuning-Part 6                                     The Art of Java Application  Performance Analysis and Tuning-Part 7

In this blog we will continue to look at some of the useful tools for analyzing the Java application programs.

Jmap (Oracle Hotspot Java VM)- Memory Map

jmap prints heap memory details of a given process or core file of a Java application. This tool available in Oracle Hotspot Java VM.  Its advanced uses are printing shared object memory maps , heap memory details of core file .

jmap’s important capabilities for memory profiling are

  1. To print java heap summary
  2. To print histogram of java live object heap

To print java heap summary

This is the simple way to get the heap usage summary. This can be used to analyze the memory usage of different parts of the Java Heap memory.

  jmap -heap <pid>

# /usr/local/jdk1.6.0_38/bin/jmap -heap 76693
Attaching to process ID 76693, please wait...
Debugger attached successfully.
Server compiler detected.

JVM version is 20.13-b02
using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 53687091200 (51200.0MB)
   NewSize          = 13421772800 (12800.0MB)
   MaxNewSize       = 13421772800 (12800.0MB)
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 16
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 536870912 (512.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 12676169728 (12088.9375MB)
   used     = 1686018912 (1607.9129333496094MB)
   free     = 10990150816 (10481.02456665039MB)
   13.30069688382134% used
Eden Space:
   capacity = 11930566656 (11377.875MB)
   used     = 1532793448 (1461.785743713379MB)
   free     = 10397773208 (9916.089256286621MB)
   12.847616481226757% used
From Space:
   capacity = 745603072 (711.0625MB)
   used     = 153225464 (146.12718963623047MB)
   free     = 592377608 (564.9353103637695MB)
   20.550540864724333% used
To Space:
   capacity = 745603072 (711.0625MB)
   used     = 0 (0.0MB)
   free     = 745603072 (711.0625MB)
   0.0% used
concurrent mark-sweep generation:
   capacity = 40265318400 (38400.0MB)
   used     = 4247009064 (4050.2634658813477MB)
   free     = 36018309336 (34349.73653411865MB)
   10.54756110906601% used
Perm Generation:
   capacity = 146186240 (139.4140625MB)
   used     = 87710416 (83.64717102050781MB)
   free     = 58475824 (55.76689147949219MB)
   59.999091569767444% used

To print histogram of Java live object heap

This is the simple way to get the live object instances in the heap memory. This gives the histogram of class names with number of instances and no. of bytes. This will be useful in OutOfMemomy and high memory usage situations. Using this histogram we can identify
which classes has more number of instances and size.

We can log this output at regular intervals and can analyze to identify objects which are growing.

# /usr/local/jdk1.6.0_38/bin/jmap -histo:live <pid>

# /usr/local/jdk1.6.0_38/bin/jmap -histo:live 76693
 num     #instances         #bytes  class name
----------------------------------------------
  1:      10362767     1175268016  [C
  2:       3779877      651446840  [Ljava.lang.Object;
  3:      11373030      454921200  java.lang.String
  4:         15872      447443072  [Lnet.sf.ehcache.store.chm.SelectableConcurrentHashMap$HashEntry;
  5:       2585762      206860960  org.hibernate.collection.PersistentList
  6:       1030813      190528920  [Ljava.util.HashMap$Entry;
  7:       3423143      136925720  java.util.ArrayList
  8:       1741450       83589600  java.util.HashMap$Entry
  9:         46832       76055168  [Lorg.hibernate.jdbc.Expectation;
 10:       1147644       73449216  com.test.product.TestJob3
 11:       1056207       67597248  com.test.product.TestJob4
 12:        685812       65837952  com.test.product.TestJob5
 13:        648750       57090000  net.sf.ehcache.Element
 14:        842762       53936768  java.util.HashMap
 15:        529534       38126448  com.test.product.TestJob2
 16:        648749       36329944  net.sf.ehcache.store.chm.SelectableConcurrentHashMap$HashEntry
 17:        883157       28261024  java.util.Arrays$ArrayList
 18:         96224       23093760  com.test.product.Test1
 19:        868136       20835264  java.lang.Long
 20:        648750       20760000  net.sf.ehcache.DefaultElementEvictionData
 21:         80046       17930304  in.co.test.product.jobs.common.TestJob
 22:        114409       16796552  <constMethodKlass>
 23:        114409       15570872  <methodKlass>
 24:         59639       15299664  [B
 25:        188040       15043200  java.util.LinkedHashMap
 26:         10634       12314264  <constantPoolKlass>
 27:        191278       12241792  java.util.LinkedHashMap$Entry

In above output, top three objects are Character array, Object array and String objects. Normally Character array, String objects tops the list.

Third line shows 11373030 string objects and these objects occupied 454921200 bytes. Observing top 50 rows gives the object usage during high memory usage scenarios.

class name column: the ‘class name’ column consists object class names.

   boolean 	    	Z
   byte 	    	B
   char 	    	C
   class or interface 	Lclassname;
   double 	    	D
   float 	    	F
   int 	        	I
   long 	    	J
   short 	    	S
   Object Array       [Lclassname

Example:

   [C is a char[]
   [S is a short[]
   [I is a int[]
   [B is a byte[]
   [[I is a int[][]
   [Ljava.lang.String;" is a class name representing a java.lang.String[] array.
   [Ljava.lang.Object is Object[]

More info at:

http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName%28%29

We can also use Jmap to take heap and core dump and analyze using jhat (or) profilers.

jhat : The jhat command parses a java heap dump file and launches a web-server. jhat enables you to browse heap dumps  using your favorite web-browser. This can be used for more advanced heap dump analysis.

Reference:

[1] http://docs.oracle.com/javase/6/docs/technotes/tools/share/jmap.html                       [2] http://docs.oracle.com/javase/6/docs/technotes/tools/share/jhat.html                        [3] http://www.lshift.net/blog/2006/03/08/java-memory-profiling-with-jmap-and-jhat        [4] http://www.herongyang.com/Java-Tools/jstack-jmap-JVM-Heap-Dump-Tool.html

Java Profilers

There are many proprietary profiling tools on the market for measuring performance and tracking down performance bottlenecks. These profilers are used to do deep analysis and profiling of java applications.

YourKit Java Profiler (Need License)

YourKit Profiler can be downloaded from http://www.yourkit.com/download/ and documentation is available at http://www.yourkit.com/docs/index.jsp.

You need to get Evaluation license copy from download site. This license key is required to connect client.

To start profiler with java application we need to add profiler agent path to the java command.

 #Linux x86, 32-bit Java
 -agentpath:yjp-11.0.8/bin/linux-x86-32/libyjpagent.so=port=9998

 #Linux x86, 64-bit Java
 -agentpath:yjp-11.0.8/bin/linux-x86-64/libyjpagent.so=port=9998

 #Solaris SPARC, 64-bit Java
 -agentpath:yjp-11.0.8/bin/solaris-sparc-64/libyjpagent.so=port=9998

 #IBM AIX PPC, 64-bit Java
 -agentpath:yjp-11.0.8/bin/aix-ppc-64/libyjpagent.so=port=9998

From Remote Windows Machine

 1. start the YourKit Profiler
 2. Enter license key details
 3. Select 'connect remote server' option
 4. Enter 'ServerIP:PortNo' ex: 192.168.9.35:9998 and connect to the server.

Most of the profiler screens are self explanatory and similar to JConsole. For more information and usage pl refer to YourKit Documentation

JProfiler Java Profiler (Need License)

http://www.ej-technologies.com/products/jprofiler/overview.html

There are other monitoring tools like JVisualVM, etc..

Advertisements
This entry was posted in java and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s