Memory Leak Detection & Prevention
📖 Concept
Memory leaks occur when objects that are no longer needed are still referenced, preventing garbage collection. In Android, Activity and Fragment leaks are the most common and dangerous.
How to detect leaks:
- LeakCanary — Automatic detection in debug builds. Watches Activities, Fragments, Views, ViewModels. Shows reference chain.
- Android Studio Memory Profiler — Live heap inspection, allocation tracking, heap dump analysis.
adb shell dumpsys meminfo— Quick memory overview per process.
Most common leak patterns in Android:
- Static reference to Activity/Context — Singleton holding Activity context
- Inner class reference — Non-static inner class holds implicit reference to outer class
- Thread/Handler leaks — Long-running operations holding Activity reference
- Unregistered callbacks — Listeners, receivers, observers not removed on destroy
- View binding not cleared — Fragment's view binding kept after onDestroyView
Leak investigation workflow:
1. Run app with LeakCanary enabled
2. Exercise the suspected flow (navigate in/out of screens)
3. LeakCanary shows toast if leak detected
4. Examine the reference chain (GC root → leak)
5. Identify the retaining reference
6. Fix and verify
Prevention checklist:
- Use
applicationContextinstead of Activity context for singletons - Clear listeners/callbacks in onStop/onDestroy
- Null out view binding in Fragment.onDestroyView
- Use WeakReference for optional callbacks
- Use lifecycle-aware components (LiveData, Flow with repeatOnLifecycle)
💻 Code Example
1// Common leak patterns and their fixes23// LEAK: ViewModel holding View reference4class BadViewModel : ViewModel() {5 var textView: TextView? = null // ❌ ViewModel outlives Activity!6}7// FIX: ViewModel exposes StateFlow, View observes it8class GoodViewModel : ViewModel() {9 private val _text = MutableStateFlow("")10 val text: StateFlow<String> = _text.asStateFlow()11}1213// LEAK: Coroutine in Activity without proper scope14class LeakyActivity : AppCompatActivity() {15 override fun onCreate(savedInstanceState: Bundle?) {16 super.onCreate(savedInstanceState)17 CoroutineScope(Dispatchers.IO).launch { // ❌ Unmanaged scope!18 delay(60_000)19 updateUI() // Activity may be destroyed20 }21 }22}23// FIX: Use lifecycleScope24class SafeActivity : AppCompatActivity() {25 override fun onCreate(savedInstanceState: Bundle?) {26 super.onCreate(savedInstanceState)27 lifecycleScope.launch { // ✅ Auto-cancelled on destroy28 delay(60_000)29 updateUI()30 }31 }32}3334// LEAK: Singleton holding Activity context35object ImageCache {36 private lateinit var context: Context37 fun init(context: Context) {38 this.context = context // ❌ If Activity context, leaked!39 }40}41// FIX: Use application context42object ImageCache {43 private lateinit var context: Context44 fun init(context: Context) {45 this.context = context.applicationContext // ✅ Application lives forever46 }47}4849// LeakCanary custom watchers50class MyApplication : Application() {51 override fun onCreate() {52 super.onCreate()53 // Watch custom objects for leaks54 val watcher = AppWatcher.objectWatcher55 // When you expect an object to be GC'd, watch it:56 // watcher.expectWeaklyReachable(myObject, "reason")57 }58}
🏋️ Practice Exercise
Practice:
- Set up LeakCanary and intentionally create 3 different types of leaks
- Use Memory Profiler to capture a heap dump and identify retained objects
- Fix a memory leak caused by a Handler posting delayed messages
- Implement a lifecycle-aware callback registration pattern
- Profile your app's memory usage across 10 screen transitions — check for growth
⚠️ Common Mistakes
Only testing on high-end devices — leaks cause OOM crashes on low-memory devices first
Using Activity context in singletons — always use applicationContext for long-lived objects
Not testing with LeakCanary in CI — add a leak detection step to your test pipeline
Assuming Kotlin's lifecycle features prevent all leaks — coroutine scope leaks are still common
💼 Interview Questions
🎤 Mock Interview
Mock interview is powered by AI for Memory Leak Detection & Prevention. Login to unlock this feature.