1<html>
2<head>
3    <title>Dalvik Heap Profiling</title>
4</head>
5
6<body>
7<h1>Dalvik Heap Profiling</h1>
8
9<p>
10The Dalvik virtual machine can produce a complete dump of the contents
11of the virtual heap.  This is very useful for debugging memory usage
12and looking for memory leaks.  Getting at the information can be tricky,
13but has become easier in recent releases.
14</p><p>
15In what follows, the version number refers to the software release
16running on the phone.  To take advantage of the DDMS integration, you will
17also need a sufficiently recent version of DDMS.
18
19
20<h2>Getting the data</h2>
21<p>
22The first step is to cause the VM to dump its status, and then pull the hprof
23data off.  The exact manner for doing so has changed over time.
24</p><p>
25There is a <code>runhat</code> shell function, added by
26<code>build/envsetup.sh</code>, that partially automates these steps.  The
27function changes in each release to accommodate newer behavior, so you have
28to be careful that you don't use the wrong version.
29</p><p>
30
31<h3>Early releases (1.0/1.1)</h3>
32<p>
33You can only generate heap data on the emulator or a device with root
34access, because of the way the dump is initiated and where the output
35files go.
36</p><p>
37Get a command shell on the device:
38<blockquote><pre>
39$ adb shell
40</pre></blockquote>
41</p><p>
42You can verify that you're running as root with the <code>id</code> command.
43The response should look like <code>uid=0(root) gid=0(root)</code>.  If not,
44type <code>su</code> and try again.  If <code>su</code> fails, you're out
45of luck.
46
47</p><p>
48Next, ensure the target directory exists:
49<blockquote><pre>
50# mkdir /data/misc
51# chmod 777 /data/misc
52</pre></blockquote>
53
54</p><p>
55Use <code>ps</code> or DDMS to determine the process ID of your application,
56then send a <code>SIGUSR1</code> to the target process:
57
58<blockquote><pre>
59# kill -10 &lt;pid&gt;
60</pre></blockquote>
61
62</p><p>
63The signal causes a GC, followed by the heap dump (to be completely
64accurate, they actually happen concurrently, but the results in the heap
65dump reflect the post-GC state).  This can take a couple of seconds,
66so you have to watch for the GC log message to know when it's complete.
67</p><p>
68Next:
69
70<blockquote><pre>
71# ls /data/misc/heap-dump*
72# exit
73</pre></blockquote>
74
75</p><p>
76Use <code>ls</code> to check the file names, then <code>exit</code> to quit
77the device command shell.
78
79</p><p>
80You should see two output files, named
81<code>/data/misc/heap-dump-BLAH-BLAH.hprof</code> and
82<code>.hprof-head</code>, where BLAH is a runtime-generated value
83that ensures the filename is unique.  Pull them off of the device and
84remove the device-side copy:
85
86<blockquote><pre>
87$ adb pull /data/misc/heap-dump-BLAH-BLAH.hprof tail.hprof
88$ adb pull /data/misc/heap-dump-BLAH-BLAH.hprof-head head.hprof
89$ adb shell rm /data/misc/heap-dump-BLAH-BLAH.hprof /data/misc/heap-dump-BLAH-BLAH.hprof-head
90</pre></blockquote>
91
92</p><p>
93Merge them together and remove the intermediates:
94
95<blockquote><pre>
96$ cat head.hprof tail.hprof &gt; dump.hprof
97$ rm head.hprof tail.hprof
98</pre></blockquote>
99
100</p><p>
101You now have the hprof dump in <code>dump.hprof</code>.
102</p><p>
103
104
105<h3>Android 1.5 ("Cupcake")</h3>
106<p>
107Some steps were taken to make this simpler.  Notably, the two output
108files are now combined for you, and a new API call was added that allows
109a program to write the dump at will to a specific file.  If you're not
110using the API call, you still need to be on an emulator or running as root.
111(For some builds, you can use <code>adb root</code> to restart the adb
112daemon as root.)
113</p><p>
114The basic procedure is the same as for 1.0/1.1, but only one file will
115appear in <code>/data/misc</code> (no <code>-head</code>), and upon
116completion you will see a log message that says "hprof: heap dump completed".
117It looks like this in the log:
118
119<blockquote><pre>
120I/dalvikvm(  289): threadid=7: reacting to signal 10
121I/dalvikvm(  289): SIGUSR1 forcing GC and HPROF dump
122I/dalvikvm(  289): hprof: dumping VM heap to "/data/misc/heap-dump-tm1240861355-pid289.hprof-hptemp".
123I/dalvikvm(  289): hprof: dumping heap strings to "/data/misc/heap-dump-tm1240861355-pid289.hprof".
124I/dalvikvm(  289): hprof: heap dump completed, temp file removed
125</pre></blockquote>
126
127</p><p>
128Summary: as above, use <code>mkdir</code> and <code>chmod</code>
129to ensure the directory exists and is writable by your application.
130Send the <code>SIGUSR1</code> or use the API call to initiate a dump.
131Use <code>adb pull &lt;dump-file&gt;</code> and <code>adb shell rm
132&lt;dump-file&gt;</code> to retrieve the file and remove it from the
133device.  The concatenation step is not needed.
134
135</p><p>
136The new API is in the <code>android.os.Debug</code> class:
137<blockquote><pre>
138public static void dumpHprofData(String fileName) throws IOException
139</pre></blockquote>
140When called, the VM will go through the same series of steps (GC and
141generate a .hprof file), but the output will be written to a file of
142your choice, e.g. <code>/sdcard/myapp.hprof</code>.  Because you're
143initiating the action from within the app, and can write the file to
144removable storage or the app's private data area, you can do this on a
145device without root access.
146
147
148<h3>Android 1.6 ("Donut")</h3>
149<p>
150No real change to the way profiling works.
151However, 1.6 introduced the <code>WRITE_EXTERNAL_STORAGE</code>
152permission, which is required to write data to the SD card.  If you're
153accustomed to writing profile data to <code>/sdcard</code>, you will
154need to enable the permission in your application's manifest.
155</p>
156
157
158<h3>Android 2.0 ("Eclair")</h3>
159<p>
160In 2.0, features were added that allow DDMS to request a heap dump on
161demand, and automatically pull the result across.  Select your application
162and click the "dump HPROF file" button in the top left.  This always
163writes files to the SD card, so
164you must have a card inserted and the permission enabled in your application.
165</p>
166
167
168<h3>Android 2.2 ("Froyo")</h3>
169<p>
170DDMS heap dump requests are now streamed directly out of the VM, removing
171the external storage requirement.
172</p>
173
174<h3>Android 2.3 ("Gingerbread")</h3>
175<p>
176The <code>kill -10</code> (<code>SIGUSR1</code>) method of generating heap
177dumps has been removed from the VM.
178</p>
179
180<h3>Android 3.0 ("Honeycomb")</h3>
181<p>
182A new command-line tool has been added:
183</p>
184<blockquote><pre>am dumpheap &lt;pid&gt; &lt;output-file-name&gt;</pre></blockquote>
185<p>
186Unlike the <code>SIGUSR1</code> approach, this does not require a rooted
187phone.  It's only necessary for the application to be debuggable (by setting
188<code>android:debuggable="true"</code> in the <code>&lt;application&gt;</code>
189element of the app manifest).  The output file is opened by "am", which
190means you can write the data to a file on <code>/sdcard</code> without
191needing the <code>WRITE_EXTERNAL_STORAGE</code> permission in your app.
192<p>
193The <code>runhat</code> shell function has been updated to use this.
194</p>
195
196<h2>Examining the data</h2>
197<p>
198The data file format was augmented slightly from the common hprof format,
199and due to licensing restrictions the modified <code>hat</code> tool cannot
200be distributed.  A conversion tool, <code>hprof-conv</code>, can be used
201to strip the Android-specific portions from the output.  This tool was
202first included in 1.5, but will work with older versions of Android.
203</p><p>
204The converted output should work with any hprof data analyzer, including
205<code>jhat</code>, which is available for free in the Sun JDK, and
206Eclipse MAT.
207
208<!-- say something about how to track down common problems, interesting
209     things to look for, ...? -->
210
211</p><p>
212<address>Copyright &copy; 2009 The Android Open Source Project</address>
213
214</body>
215</html>
216