androidengineers.Book a session

Memory Management

Memory Profiler & LeakCanary

article25 minMedium

The Android Memory Profiler and LeakCanary are the two tools you'll spend the most time with when hunting memory issues. They complement each other: the Profiler shows the overall heap picture; LeakCanary pinpoints the exact reference chain causing a leak.

Android Studio Memory Profiler

How to access: Run → Profile app → Memory tab → Start profiler.

Key Views

Heap dump — snapshot of all live objects on the heap. Captures:

  • Object count per class
  • Shallow size (the object's own memory)
  • Retained size (total memory freed if this object were collected)
Run the app → perform the suspicious action several times
→ click "Dump Java Heap" → wait for capture

Allocation tracking — records every object allocation over a time window:

Click "Record" → perform the action → "Stop"
→ sort by "Count" or "Size"
→ look for objects that grow unboundedly

Reading a Heap Dump

  1. Sort by Retained Size descending — biggest memory holders at the top
  2. Look for Activity or Fragment instances with count > 1 (leak indicator)
  3. Click an instance → References panel shows what's holding it
  4. Follow the chain from GC Root → leaked object
GC Root → MainThread.localVariables
  → Handler → Activity (should be destroyed)
  → View (inside the Activity)

LeakCanary

LeakCanary automates heap dump analysis. It detects when an Activity/Fragment should be collected but isn't, takes a heap dump, analyzes it, and shows a human-readable leak trace.

Setup

// build.gradle.kts — add to debug only
dependencies {
    debugImplementation("com.squareup.leakcanary:leakcanary-android:2.12")
}
// No Application.onCreate code needed — LeakCanary auto-installs itself

Reading a Leak Trace

┬───
│ GC Root: Thread (main thread)
│
├─ android.os.Handler
│    leaking: NO (Handler is reachable)
│    handler type: MyActivity$Companion$myHandler$1
│
├─ MyActivity
│    leaking: YES (Activity destroyed)
│    reason: MyActivity#mDestroyed is true
│
╰→ android.widget.TextView
     leaking: YES (View attached to a destroyed Activity)

Read from bottom to top:

  • Bottom: the leaking object (Activity/View)
  • Top: what's holding the reference
  • The fix is at the top: stop the top-most object from holding the reference

Custom Watch Targets

By default, LeakCanary watches Activities and Fragments. Add custom objects:

// Watch when a ViewModel should be cleared
class MyViewModel : ViewModel() {
    override fun onCleared() {
        AppWatcher.objectWatcher.expectWeaklyReachable(this, "ViewModel was cleared")
    }
}

// Watch a custom object
AppWatcher.objectWatcher.expectWeaklyReachable(
    someObject,
    "Description of where this object was created"
)

Memory Profiler Workflow for Suspected Leaks

1. Launch app → go to the screen with the suspected leak
2. Press Back or finish the Activity
3. Force GC: click "Force GC" button in profiler
4. Dump heap
5. Search for the Activity class in the heap dump
6. If Count > 0 → it's leaked
7. Click the instance → References → trace the chain

Common LeakCanary Findings and Fixes

Leak trace signatureFix
InputMethodManager → ActivityPlatform bug; no fix needed (LeakCanary ignores known platform leaks)
Handler → ActivityRemove callbacks in onDestroy/onPause
Static field → ActivityUse applicationContext; don't store Activity in statics
Cursor not closedClose cursors in finally blocks
RecyclerView.Adapter → FragmentSet adapter to null in onDestroyView

Key Takeaways

ToolBest for
Memory Profiler (heap dump)Understanding what's using heap; finding leaked instances
Memory Profiler (allocation)Finding which code path allocates too many objects
LeakCanaryAutomated leak detection with exact reference chain
AppWatcher.objectWatcherVerifying custom objects are collected when expected

YOUR LEARNING JOURNEY

0 of 177 available lessons completed

Progress saved in this browser. No account needed.
Memory Profiler & LeakCanary | Android System Design | Android Engineers