Monday September 19, 2005 Heap dumps are back with a vengeance! The HPROF agent has been around since 1998 and early betas of J2SETM 1.2. One of its more useful features, at the time, was the ability to generate a heap dump. The heap dump is a dump of all the live objects and classes. The HPROF agent also records where objects are allocated and these are written to the dump file too. Heap dumps aren't very useful without a tool to read them but a novel tool called the Heap Analysis Tool (HAT), courtesy of Bill Foote, was released at around the same time. HAT was very useful as it allowed developers to browse the heap dump, and do rudimentary queries to debug memory leak problems.
HPROF fell on hard times in J2SE 1.3 and 1.4. One consequence of this was that the heap dumps weren't always
readable by HAT. The background to this is that HPROF used an experimental profiling interface called
JVMPI.
JVMPI was designed for the original classic VM where it worked well. An implementation of JVMPI was created for
its replacement, the HotSpotTM VM, but it was problematic. The root of the
issue is that JVMPI wasn't really designed with modern virtual machines in mind. It required events from places
that are highly optimized in modern virtual machines. HPROF required the
OBJECT_ALLOC
event when started with the heap=dump option. This was one of the more troublesome events as it
inhibited many optimizations, and didn't work with all garbage collection implementations.
HPROF returned to its glory days in J2SE 5.0 thanks to a complete make over by Kelly O'Hair The catalyst for the make over (actually a complete re-write) was JSR-163 which defined a new tool interface called the JVMTM Tool Interface. JVM TI broke from the past and didn't provide some events that one might expect in a profiling interface. In particular it doesn't provide an object allocation event - in its place the interface provides support for tools to do bytecode instrumentation. With HPROF re-implemented it meant that heap dumps were working again. HAT was back in business!
In Mustang (Java SE 6.0), HPROF gets new two new siblings which bring new ways to generate heap dumps.
The built-in heap dumper can also be used to take a snapshot of the heap at other times. This is done using the using the jmap command line utility or jconsole monitoring and management console. This is also very useful - if you are monitoring an application with jconsole and you see the heap usage growing over time then you might want to take a snapshot of the heap to see what is going on.
Before we meet the new heap dumpers it is important to mention that they generate simple heap dumps. That is, the dump files contain information about all the objects and classes in the heap but they do not contain information about where the objects are allocated. If you need this information then it is best to run with a JVM TI agent that records this. The NetBeans Profiler is particularly good at this.
Now let us meet the new heap dumpers ...
First, here is an example where we run an application, called ConsumeHeap, with a flag that tells the HotSpot VM to generate a generate a heap dump when we run out of memory:
$ java -XX:+HeapDumpOnOutOfMemoryError -mn256m -mx512m ConsumeHeap
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid2262.hprof ...
Heap dump file created [531535128 bytes in 14.691 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at ConsumeHeap$BigObject.(ConsumeHeap.java:22)
at ConsumeHeap.main(ConsumeHeap.java:32)
$
ConsumeHeap, as expected, fills up the java heap and runs out of memory. When java.lang.OutOfMemoryError is thrown a heap dump file is created. In this case the file is 507MB and is created as java_pid2262.hprof in the current directory. If you don't want big dump files in the application working directory then the HeapDumpPath option can be used to specify an alternative location - for example -XX:HeapDumpPath=/disk2/dumps will cause the heap dump to be generated in the /disk2/dumps directory.
[As a complete aside, notice that the java.lang.OutOfMemoryError has a stack trace - this is also new in Mustang - in J2SE 5.0 the OutOfMemoryError would have been thrown without any stack trace]
Now let's look at a second example:
C:\> jmap -dump:file=app.bin 345 Dumping heap to C:\temp\app.bin ... Heap dump file created C:\>
This example uses the
jmap utility to generate
a heap dump of the java application running as process 345. Astute readers will observe that
this example was done on Microsoft Windows but the jmap utility was only included
with the J2SE 5.0 releases for Solaris and Linux. This is semi-true for Mustang too but
jmap.exe is included and supports a subset of the options available on the other
platforms. In particular the -dump option is there on all platforms.
Now let us look at an example that generates a heap dump from a core file. As crashes are rare I've cheated a bit
by getting a core file with the Solaris gcore command:
$ gcore 5831 gcore: core.5831 dumped $ jmap -dump:file=app.bin `which java` core.5831 Attaching to core core.5831 from executable /opt/java/bin/java, please wait... Debugger attached successfully. Server compiler detected. JVM version is 1.6.0-ea-b52 Dumping heap to app.bin ... Unknown oop at 0xf14b8650 Oop's klass is 0xf14b54d0 Unknown oop at 0xf14e67a8 Oop's klass is null Heap dump file created $
The arguments after the -dump option are the executable and the core image file. I
used `which java` which gives me the pathname of java. Needless to say these need to
match. Less obvious is that you that you can only use jmap from the same JDK build as the executable too. So for
example, if you have a core file from 6.0-ea-b52 then you need to use jmap from 6.0-ea-b52 to generate a heap
dump from the core file.
You might notice a few warnings in the output. The messages Unknown oop at ... might be a bit
off-putting but remember that the core image is taken at an arbitrary time. There is no guarantee that the heap
and other data structures are in a consistent state when the crash dump is obtained.
At this point your disks are probably full of heap dumps and you are wondering how to examine them. In the introduction I mentioned the Heap Analysis Tool (HAT). HAT is now included in Mustang (since b51) as a command line utility called "jhat".
Getting started with jhat is easy - just give it the name of the heap dump file:
$ jhat java_pid2278.hprof Started HTTP server on port 7000 Reading from java_pid2278.hprof... Dump file created Sun Sep 18 17:18:38 BST 2005 Snapshot read, resolving... Resolving 6162194 objects... Chasing references, expect 12324 dots......................................................... Eliminating duplicate references.............................................................. Snapshot resolved. Server is ready.
At this point HAT has started a HTTP server on port 7000. Point your browser to
http://localhost:7000 to connect to the HAT server.
[HAT requires a lot of memory so if you try it and it fails with OutOfMemoryError then you might need to give it
a larger heap size (for example: jhat -J-mx512m java_pid2278.hprof). The memory consumption of HAT
is currently being worked on - expect to see improvements in b54 or b55.]
When you connect to the HAT server you should see a list of all the classes in the heap dump. This is the
All Classes query. Scroll to the bottom of the page to see the other queries.
A full description of all the queries is more than I have time for today but you can read more in the HAT
README.
Those that are familiar with HAT will not see many differences between HAT 1.1 and jhat in b52. However you can expect improvements in b53 (should be available on 9/23). For starters there are a number of robustness improvements - like being able to to parse incomplete and truncated heap dumps. There are also various fixes and finally HAT will be able to read heap dumps generated on 64-bit systems.
Small improvements aside, a useful (and very interesting) addition in b53 is that Sundar Athijegannathan has added a scripting interface to HAT. This make use of the new scripting API. This addition allows developers to enter arbitrary queries into browser and they aren't tied to canned queries that HAT provides. Keep an eye on Sundar's blog for updates on this topic.
To sum up: Mustang (Java SE 6.0) allows heap dumps to be obtained at out of memory time, at any time during the life time of the application, or even after an applications dies with a crash. Also with jhat included in the JDK it means that there is a simple out of the box utility to examine the heap dumps and do rudimentary memory analysis. So heap dumps are back, and back with a vengeance! ( Sep 19 2005, 08:31:34 AM PDT ) Permalink Comments [37]
Posted by Chrsi Markle on October 17, 2005 at 09:43 PM PDT #
Posted by Alan Bateman on October 18, 2005 at 01:50 AM PDT #
Posted by Indrajit Poddar on February 15, 2006 at 01:12 PM PST #
The heap dump is in binary format (format=b). If you want an ascii file then it would be easy to write something to process the dump and emit an ascii version.
jmap -help will give you the full list of options. Here's the output on Solaris or Linux:
$ jmap -help Usage: jmap [option] <pid> (to connect to running process) jmap [option] <executable <core> (to connect to a core file) jmap [option] [server_id@]<remote server IP or hostname> (to connect to remote debug server) where <option> is one of: <none> to print same info as Solaris pmap -heap to print java heap summary -histo to print histogram of java object heap -permstat to print permanent generation statistics -finalizerinfo to print information on objects awaiting finalization -dump:<dump-options> to dump java heap in hprof binary format dump-options: format=b binary format file=<file> dump heap to <file> Example: jmap -dump:format=b,file=heap.bin <pid> -F force. Use with -dump:<dump-options> <pid> or -histo to force a heap dump or histogram when <pid> does not respond. -h | -help to print this help message -J<flag> to pass <flag> directly to the runtime systemand on Windows:
C:\> jmap -help Usage: jmap -histo <pid> (to connect to running process and print histogram of java object heap jmap -dump:<dump-options> <pid> (to connect to running process and dump java heap) dump-options: format=b binary default file=<file> dump heap to <file> Example: jmap -dump:format=b,file=heap.bin <pid>The man page on java.sun.com will be updated post beta.
Posted by Alan Bateman on February 16, 2006 at 01:42 AM PST #
Posted by Sameer on April 11, 2006 at 06:05 AM PDT #
Posted by Veerendra Chirala on May 19, 2006 at 01:17 PM PDT #
Posted by Bill Au on June 08, 2006 at 09:10 AM PDT #
However, after successfully connecting to the VM process and working for a while, all I got is:
Exception in thread "main" sun.jvm.hotspot.debugger.UnalignedAddressException: Trying to read at address: 0x000000000000000a with alignment: 4 at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$1.checkAlignment(LinuxDebuggerLocal.java:163) at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.readCInteger(LinuxDebuggerLocal.java:449) at sun.jvm.hotspot.debugger.DebuggerBase.readAddressValue(DebuggerBase.java:425) at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.readOopHandle(LinuxDebuggerLocal.java:413) at sun.jvm.hotspot.debugger.linux.LinuxAddress.getOopHandleAt(LinuxAddress.java:98) at sun.jvm.hotspot.oops.Oop.getKlassForOopHandle(Oop.java:175) at sun.jvm.hotspot.oops.ObjectHeap.newOop(ObjectHeap.java:346) at sun.jvm.hotspot.runtime.JavaThread.getThreadObj(JavaThread.java:333) at sun.jvm.hotspot.utilities.AbstractHeapGraphWriter.writeJavaThreads(AbstractHeapGraphWriter.java:113) at sun.jvm.hotspot.utilities.AbstractHeapGraphWriter.write(AbstractHeapGraphWriter.java:98) at sun.jvm.hotspot.utilities.HeapHprofBinWriter.write(HeapHprofBinWriter.java:357) at sun.jvm.hotspot.tools.JMap.writeHeapHprofBin(JMap.java:134) at sun.jvm.hotspot.tools.JMap.run(JMap.java:71) at sun.jvm.hotspot.tools.Tool.start(Tool.java:204) at sun.jvm.hotspot.tools.JMap.main(JMap.java:126)Do you per chance know anything I could do about it? Thanks, Jörg.Posted by Jörg von Frantzius on July 20, 2006 at 04:54 AM PDT #
However, after successfully connecting to the VM process and working for a while, all I got is:
Exception in thread "main" sun.jvm.hotspot.debugger.UnalignedAddressException: Trying to read at address: 0x000000000000000a with alignment: 4 at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$1.checkAlignment(LinuxDebuggerLocal.java:163) at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.readCInteger(LinuxDebuggerLocal.java:449) at sun.jvm.hotspot.debugger.DebuggerBase.readAddressValue(DebuggerBase.java:425) at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.readOopHandle(LinuxDebuggerLocal.java:413) at sun.jvm.hotspot.debugger.linux.LinuxAddress.getOopHandleAt(LinuxAddress.java:98) at sun.jvm.hotspot.oops.Oop.getKlassForOopHandle(Oop.java:175) at sun.jvm.hotspot.oops.ObjectHeap.newOop(ObjectHeap.java:346) at sun.jvm.hotspot.runtime.JavaThread.getThreadObj(JavaThread.java:333) at sun.jvm.hotspot.utilities.AbstractHeapGraphWriter.writeJavaThreads(AbstractHeapGraphWriter.java:113) at sun.jvm.hotspot.utilities.AbstractHeapGraphWriter.write(AbstractHeapGraphWriter.java:98) at sun.jvm.hotspot.utilities.HeapHprofBinWriter.write(HeapHprofBinWriter.java:357) at sun.jvm.hotspot.tools.JMap.writeHeapHprofBin(JMap.java:134) at sun.jvm.hotspot.tools.JMap.run(JMap.java:71) at sun.jvm.hotspot.tools.Tool.start(Tool.java:204) at sun.jvm.hotspot.tools.JMap.main(JMap.java:126)Do you per chance know anything I could do about it? Thanks, Jörg.Posted by Jörg von Frantzius on July 20, 2006 at 05:04 AM PDT #
Posted by Alan on July 20, 2006 at 07:30 AM PDT #
Posted by chethan on October 20, 2006 at 02:20 AM PDT #
Posted by Alan on October 20, 2006 at 02:41 AM PDT #
Posted by Dave on November 20, 2006 at 05:56 AM PST #
Posted by Dave on November 20, 2006 at 06:01 AM PST #
Posted by Alan on November 20, 2006 at 06:13 AM PST #
Posted by varsha on March 26, 2007 at 11:45 PM PDT #
Posted by A. Sundararajan on March 27, 2007 at 12:54 AM PDT #
Posted by varsha on March 27, 2007 at 02:03 AM PDT #
Posted by Alan on March 27, 2007 at 02:06 AM PDT #
Posted by varsha on March 27, 2007 at 02:14 AM PDT #
Posted by Alan on March 27, 2007 at 02:25 AM PDT #
Posted by Lynn on April 02, 2007 at 11:22 AM PDT #
Posted by Alan on April 05, 2007 at 01:04 AM PDT #
Posted by 167.202.196.72 on June 07, 2007 at 12:46 AM PDT #
Posted by Rene A. on June 28, 2007 at 08:21 AM PDT #
Posted by A. on June 28, 2007 at 10:04 AM PDT #
Just to get this right. I'm running on 1.5.0_b5, and to get the -XX:+HeapDumpOnOutOfMemoryError option, I know I have to update at least to 1.5.0_07.
Since I'm searching for a way to get a heapdump from a production server (were I can't easily upgrade the JDK), I hoped I can get away with the following:
1) jps
2) jmap -dump:format=b,file=prog.bin pid
But it seems, that I would simply be the best to "just upgrade" to a newer 1.5.0_xx JVM and have -XX:+HeapDumpOnOutOfMemoryError available :)
Posted by Rene A. on June 29, 2007 at 12:48 AM PDT #
Posted by A. on June 29, 2007 at 01:02 AM PDT #
-------------------------
DUMP HEAP 0x02
ALLOC SITES 0x03
HEAP SUMMARY 0x04
EXIT THE VM 0x05
DUMP TRACES 0x06
CPU SAMPLES 0x07
CONTROL 0x08
EOF 0xFF
----------------------
I got the info from hprof manual. ..demo\jvmti\hprof\src\manual.html
e.g. can I use the code as below to ask hprof to do heap dump?
---------------------
outputStream = new DataOutputStream(_socket.getOutputStream());
byte[] cmd = new byte[1];
cmd[0] = 0x02; //DUMP HEAP
outputStream.write(cmd);
----------------------
Posted by hobby on July 04, 2007 at 09:25 AM PDT #
Posted by hobby on July 05, 2007 at 01:35 AM PDT #
Posted by Veerendra Chirala on July 24, 2007 at 12:51 PM PDT #
Posted by A. on July 24, 2007 at 12:57 PM PDT #
Alan, My java-app in production is based on 1.5.0_11. So to troubleshoot the hangs and OOME, as i get these option, are they correct:
=> ctrl+brk on-demand dumps to be analyzed with jhat cannot be taken in the 1.5.0_11 , and have to upgrade to 1.5.0_17 (5.0u17) with XX:+HeapDumpOnCtrlBreak =OR= upgrade to 1.6 updt2 and use jmap -dump and jhat.
Q1. Is it use safe to use XX:+HeapDumpOnCtrlBreak and -XX:+HeapDumpOnOutOfMemoryError in production would not affect performance
Q2. Can I use windows 1.6 jstack on application based on jvm of 1.5 version? Doing this gives me error pre-6.0 jvm dll.
Whats the way to get stack trace of hung 1.5.0_11 process?
Nilesh
Posted by Nilesh on August 29, 2007 at 09:09 AM PDT #
I see at sun website, the lates jdk5 is u14, looks like u17 will take a long time to be available.
I see XX:+HeapDumpOnCtrlBreak is already available on u14, but JDK6 doesn't support it.
Posted by Claudio Miranda on November 14, 2007 at 04:39 AM PST #
You don't need HeapDumpOnCtrlBreak in jdk6. It is much easier to use jmap with the -dump option.
Posted by 192.18.43.225 on November 14, 2007 at 04:41 AM PST #
I can get heap dump when running JDK 1.5 or 1.6 but I need to try and get heap dump when running on a live system running jre 1.5.11. We don't really want to install full JDK on live system - can you tell me which jars are required? Thanks.
Posted by John J Smith on November 26, 2007 at 06:19 AM PST #
Hi,
I am taking heap dump using javac
javac -J-agentlib:hprof=heap=all
The heap dump file generated doesnt have objects related to my product classes. It has only core objects related to built in java classes.
Please help me with this to take heap dump of entire heap.
Also, looks like jmap utility is not supported with jdk 1.5
-Thanks
Aditya
Posted by Aditya on February 25, 2008 at 10:07 PM PST #