The Dalvik virtual machine can produce a complete dump of the contents of the virtual heap. This is very useful for debugging memory usage and looking for memory leaks. Getting at the information can be tricky, but has become easier in recent releases.
In what follows, the version number refers to the software release running on the phone. To take advantage of the DDMS integration, you will also need a sufficiently recent version of DDMS.
The first step is to cause the VM to dump its status, and then pull the hprof data off. The exact manner for doing so has changed over time.
There is a runhat
shell function, added by
build/envsetup.sh
, that partially automates these steps. The
function changes in each release to accommodate newer behavior, so you have
to be careful that you don't use the wrong version.
You can only generate heap data on the emulator or a device with root access, because of the way the dump is initiated and where the output files go.
Get a command shell on the device:
$ adb shell
You can verify that you're running as root with the id
command.
The response should look like uid=0(root) gid=0(root)
. If not,
type su
and try again. If su
fails, you're out
of luck.
Next, ensure the target directory exists:
# mkdir /data/misc # chmod 777 /data/misc
Use ps
or DDMS to determine the process ID of your application,
then send a SIGUSR1
to the target process:
# kill -10 <pid>
The signal causes a GC, followed by the heap dump (to be completely accurate, they actually happen concurrently, but the results in the heap dump reflect the post-GC state). This can take a couple of seconds, so you have to watch for the GC log message to know when it's complete.
Next:
# ls /data/misc/heap-dump* # exit
Use ls
to check the file names, then exit
to quit
the device command shell.
You should see two output files, named
/data/misc/heap-dump-BLAH-BLAH.hprof
and
.hprof-head
, where BLAH is a runtime-generated value
that ensures the filename is unique. Pull them off of the device and
remove the device-side copy:
$ adb pull /data/misc/heap-dump-BLAH-BLAH.hprof tail.hprof $ adb pull /data/misc/heap-dump-BLAH-BLAH.hprof-head head.hprof $ adb shell rm /data/misc/heap-dump-BLAH-BLAH.hprof /data/misc/heap-dump-BLAH-BLAH.hprof-head
Merge them together and remove the intermediates:
$ cat head.hprof tail.hprof > dump.hprof $ rm head.hprof tail.hprof
You now have the hprof dump in dump.hprof
.
Some steps were taken to make this simpler. Notably, the two output
files are now combined for you, and a new API call was added that allows
a program to write the dump at will to a specific file. If you're not
using the API call, you still need to be on an emulator or running as root.
(For some builds, you can use adb root
to restart the adb
daemon as root.)
The basic procedure is the same as for 1.0/1.1, but only one file will
appear in /data/misc
(no -head
), and upon
completion you will see a log message that says "hprof: heap dump completed".
It looks like this in the log:
I/dalvikvm( 289): threadid=7: reacting to signal 10 I/dalvikvm( 289): SIGUSR1 forcing GC and HPROF dump I/dalvikvm( 289): hprof: dumping VM heap to "/data/misc/heap-dump-tm1240861355-pid289.hprof-hptemp". I/dalvikvm( 289): hprof: dumping heap strings to "/data/misc/heap-dump-tm1240861355-pid289.hprof". I/dalvikvm( 289): hprof: heap dump completed, temp file removed
Summary: as above, use mkdir
and chmod
to ensure the directory exists and is writable by your application.
Send the SIGUSR1
or use the API call to initiate a dump.
Use adb pull <dump-file>
and adb shell rm
<dump-file>
to retrieve the file and remove it from the
device. The concatenation step is not needed.
The new API is in the android.os.Debug
class:
When called, the VM will go through the same series of steps (GC and generate a .hprof file), but the output will be written to a file of your choice, e.g.public static void dumpHprofData(String fileName) throws IOException
/sdcard/myapp.hprof
. Because you're
initiating the action from within the app, and can write the file to
removable storage or the app's private data area, you can do this on a
device without root access.
No real change to the way profiling works.
However, 1.6 introduced the WRITE_EXTERNAL_STORAGE
permission, which is required to write data to the SD card. If you're
accustomed to writing profile data to /sdcard
, you will
need to enable the permission in your application's manifest.
In 2.0, features were added that allow DDMS to request a heap dump on demand, and automatically pull the result across. Select your application and click the "dump HPROF file" button in the top left. This always writes files to the SD card, so you must have a card inserted and the permission enabled in your application.
DDMS heap dump requests are now streamed directly out of the VM, removing the external storage requirement.
The kill -10
(SIGUSR1
) method of generating heap
dumps has been removed from the VM.
A new command-line tool has been added:
am dumpheap <pid> <output-file-name>
Unlike the SIGUSR1
approach, this does not require a rooted
phone. It's only necessary for the application to be debuggable (by setting
android:debuggable="true"
in the <application>
element of the app manifest). The output file is opened by "am", which
means you can write the data to a file on /sdcard
without
needing the WRITE_EXTERNAL_STORAGE
permission in your app.
The runhat
shell function has been updated to use this.
The data file format was augmented slightly from the common hprof format,
and due to licensing restrictions the modified hat
tool cannot
be distributed. A conversion tool, hprof-conv
, can be used
to strip the Android-specific portions from the output. This tool was
first included in 1.5, but will work with older versions of Android.
The converted output should work with any hprof data analyzer, including
jhat
, which is available for free in the Sun JDK, and
Eclipse MAT.
Copyright © 2009 The Android Open Source Project