You may have noticed that mobile applications do not have a “Quit” button. They essentially run forever, until either the user or the operating system kills the application. This means that if your application has a memory leak, even a small one, the memory usage of the application can grow very large over time.
I had to track down a memory leak in our native code just this week, and it was a bit of a pain so I thought I would share my findings. I am using OSX for development, so if you are on Windows you can figure out the corresponding location of the various files.
First you will need to configure the Android utility ddms (Dalvik Debug Monitor) to display the native heap. You do this by editing the ddms.cfg in the directory “.android” in your home directory. Add the line “native=true”. Now when you launch ddms, you will see a new tab for the native heap:
Now you launch your application on your phone while it is plugged into the USB port. You click the “snapshot current native heap usage” button and … nothing happens.
It turns out that native allocations are not tracked by Android unless you are using the debug malloc library. You can enable this by running the following commands:
adb shell setprop libc.debug.malloc 1
adb shell stop
adb shell start
Now you click the snapshot button and … still nothing happens.
Guess what – unless your phone is rooted, you won’t be able to set this property and get the native heap allocation information out.
So now what? You have two options. Root your phone, or use the emulator. The Android emulator is extremely slow, but in this case, I was able to use it to reproduce the problem that caused the leak. I created a virtual Android device for 4.0 and launched the emulator. After running the commands to enable debug mallocs, the native snapshot finally returned allocation data.
As I searched the web to find this information, I saw several questions asking how you would use this heap snapshot tool to find a leak. It is really straightforward. Just take a snapshot at a point before the leak, take another snapshot after the leak, and then diff the two snapshots with your favorite diff tool to see what allocations are still hanging around after the leak.
So what was the particular leak I found? It turned out to be a texture for a 3D model. The texture was about a meg in size, which corresponded to the 1meg leak I was seeing each time a model was loaded and unloaded.