Managing Memory in Android
Android devices have strictly limited memory. Even though the Android Runtime (ART) features an advanced Garbage Collector (GC), applications and system services can still leak memory. A memory leak occurs when an object is no longer needed but is still referenced by other active objects, preventing the GC from reclaiming its memory.
Over time, leaks cause the process heap to grow until it hits the system-defined limit, resulting in an OutOfMemoryError (OOM) crash. In AOSP, leaks in long-running processes like system_server or SurfaceFlinger are catastrophic, eventually requiring a hard reboot to recover.
Java Heap Dumps with ADB
To diagnose a Java memory leak, you need a snapshot of the process's memory at a specific point in time, known as a heap dump (.hprof file).
You can generate a heap dump manually using the Android Debug Bridge (ADB). First, find the Process ID (PID) of the app or service.
adb shell pidof com.example.myapp
Then, use the am dumpheap command:
adb shell am dumpheap <PID> /data/local/tmp/heap.hprof
adb pull /data/local/tmp/heap.hprof .
If you are dealing with a system app or a process that crashes quickly, you can configure Android to automatically dump the heap when an OOM occurs by setting properties:
adb shell setprop dalvik.vm.heapdump.on.oom true
Analyzing Heap Dumps
Android Studio provides an excellent built-in Memory Profiler that can open and analyze .hprof files.
If you are using external tools like Eclipse MAT (Memory Analyzer Tool) or YourKit, you must first convert the Android-specific HPROF format to the standard Java SE HPROF format using the hprof-conv tool provided in the Android SDK:
hprof-conv heap.hprof standard_heap.hprof
When analyzing the dump, look for:
- Dominator Tree: Which objects retain the most memory?
- Instances: Sort classes by the number of instances. If you see hundreds of
MainActivityinstances, you have a context leak. - References: Find a leaked object and trace its "Path to GC Root". This shows you the exact chain of strong references keeping the object alive (e.g., a static variable holding a reference to a View).
Native Heap Profiling with Perfetto heapprofd
Memory leaks in C/C++ code (native layer) are notoriously difficult to track because there is no Garbage Collector to manage references.
Historically, developers used tools like malloc_debug. Today, the standard for AOSP is Perfetto's heapprofd.
heapprofd intercepts malloc, calloc, and free calls. It records the call stack for every allocation. By taking a snapshot of all active allocations, it can show you exactly where leaked memory was originally allocated.
To use it, you configure a Perfetto trace to target a specific process:
data_sources {
config {
name: "android.heapprofd"
heapprofd_config {
sampling_interval_bytes: 4096
process_cmdline: "surfaceflinger"
}
}
}
When you load the resulting trace into ui.perfetto.dev, you will see a Flamegraph. The wider the block in the flamegraph, the more memory was allocated by that specific function call stack and not freed.
Valgrind and AddressSanitizer (ASan)
For deep native memory analysis, AOSP supports specialized compiler instrumentation.
AddressSanitizer (ASan)
ASan is a fast memory error detector built into LLVM/Clang. It instruments memory accesses during compilation to detect use-after-free, buffer overflows, and memory leaks.
To enable ASan for a specific module in AOSP, you modify its Android.bp:
sanitize: {
address: true,
}
When an ASan-instrumented binary encounters a memory violation or a leak upon exit, it prints a highly detailed stack trace to Logcat and instantly crashes, preventing silent corruption.
Hardware-Assisted AddressSanitizer (HWASan)
For ARM64 devices, HWASan uses the Top-Byte Ignore (TBI) feature of the ARM architecture to achieve the same results as ASan but with significantly lower memory overhead, making it suitable for instrumenting the entire operating system on test builds.
LeakCanary Integration
For application development, Square's LeakCanary is the industry standard for automated leak detection.
It works by hooking into the Android lifecycle. When an Activity or Fragment is destroyed, LeakCanary passes a weak reference to an internal ObjectWatcher. After five seconds, if the object has not been garbage collected, LeakCanary automatically triggers a heap dump, parses it using the Shark library, and displays a notification with the exact reference chain causing the leak.
While LeakCanary is an app-level library, its concepts (weak reference tracking and automated heap analysis) are highly relevant for building robust system services in AOSP.