1*d9e8da70SAndroid Build Coastguard WorkerA memory leak is a programming error that causes an application to keep a reference to an object that is no longer needed. Somewhere in the code, there's a reference that should have been cleared and wasn't. 2*d9e8da70SAndroid Build Coastguard Worker 3*d9e8da70SAndroid Build Coastguard WorkerFollow these 4 steps to fix memory leaks: 4*d9e8da70SAndroid Build Coastguard Worker 5*d9e8da70SAndroid Build Coastguard Worker1. Find the leak trace. 6*d9e8da70SAndroid Build Coastguard Worker2. Narrow down the suspect references. 7*d9e8da70SAndroid Build Coastguard Worker3. Find the reference causing the leak. 8*d9e8da70SAndroid Build Coastguard Worker4. Fix the leak. 9*d9e8da70SAndroid Build Coastguard Worker 10*d9e8da70SAndroid Build Coastguard WorkerLeakCanary helps you with the first two steps. The last two steps are up to you! 11*d9e8da70SAndroid Build Coastguard Worker 12*d9e8da70SAndroid Build Coastguard Worker## 1. Find the leak trace 13*d9e8da70SAndroid Build Coastguard Worker 14*d9e8da70SAndroid Build Coastguard WorkerA **leak trace** is a shorter name for the *best strong reference path from garbage collection roots to the retained object*, ie the path of references that is holding an object in memory, therefore preventing it from being garbage collected. 15*d9e8da70SAndroid Build Coastguard Worker 16*d9e8da70SAndroid Build Coastguard WorkerFor example, let's store a helper singleton in a static field: 17*d9e8da70SAndroid Build Coastguard Worker 18*d9e8da70SAndroid Build Coastguard Worker```java 19*d9e8da70SAndroid Build Coastguard Workerclass Helper { 20*d9e8da70SAndroid Build Coastguard Worker} 21*d9e8da70SAndroid Build Coastguard Worker 22*d9e8da70SAndroid Build Coastguard Workerclass Utils { 23*d9e8da70SAndroid Build Coastguard Worker public static Helper helper = new Helper(); 24*d9e8da70SAndroid Build Coastguard Worker} 25*d9e8da70SAndroid Build Coastguard Worker``` 26*d9e8da70SAndroid Build Coastguard Worker 27*d9e8da70SAndroid Build Coastguard WorkerLet's tell LeakCanary that the singleton instance is expected to be garbage collected: 28*d9e8da70SAndroid Build Coastguard Worker 29*d9e8da70SAndroid Build Coastguard Worker``` 30*d9e8da70SAndroid Build Coastguard WorkerAppWatcher.objectWatcher.watch(Utils.helper) 31*d9e8da70SAndroid Build Coastguard Worker``` 32*d9e8da70SAndroid Build Coastguard Worker 33*d9e8da70SAndroid Build Coastguard WorkerThe leak trace for that singleton looks like this: 34*d9e8da70SAndroid Build Coastguard Worker 35*d9e8da70SAndroid Build Coastguard Worker``` 36*d9e8da70SAndroid Build Coastguard Worker┬─── 37*d9e8da70SAndroid Build Coastguard Worker│ GC Root: Local variable in native code 38*d9e8da70SAndroid Build Coastguard Worker│ 39*d9e8da70SAndroid Build Coastguard Worker├─ dalvik.system.PathClassLoader instance 40*d9e8da70SAndroid Build Coastguard Worker│ ↓ PathClassLoader.runtimeInternalObjects 41*d9e8da70SAndroid Build Coastguard Worker├─ java.lang.Object[] array 42*d9e8da70SAndroid Build Coastguard Worker│ ↓ Object[].[43] 43*d9e8da70SAndroid Build Coastguard Worker├─ com.example.Utils class 44*d9e8da70SAndroid Build Coastguard Worker│ ↓ static Utils.helper 45*d9e8da70SAndroid Build Coastguard Worker╰→ java.example.Helper 46*d9e8da70SAndroid Build Coastguard Worker``` 47*d9e8da70SAndroid Build Coastguard Worker 48*d9e8da70SAndroid Build Coastguard WorkerLet's break it down! At the top, a `PathClassLoader` instance is held by a **garbage collection (GC) root**, more specifically a local variable in native code. GC roots are special objects that are always reachable, ie they cannot be garbage collected. There are 4 main types of GC root: 49*d9e8da70SAndroid Build Coastguard Worker 50*d9e8da70SAndroid Build Coastguard Worker* **Local variables**, which belong to the stack of a thread. 51*d9e8da70SAndroid Build Coastguard Worker* Instances of **active Java threads**. 52*d9e8da70SAndroid Build Coastguard Worker* **System Classes**, which never unload. 53*d9e8da70SAndroid Build Coastguard Worker* **Native references**, which are controlled by native code. 54*d9e8da70SAndroid Build Coastguard Worker 55*d9e8da70SAndroid Build Coastguard Worker``` 56*d9e8da70SAndroid Build Coastguard Worker┬─── 57*d9e8da70SAndroid Build Coastguard Worker│ GC Root: Local variable in native code 58*d9e8da70SAndroid Build Coastguard Worker│ 59*d9e8da70SAndroid Build Coastguard Worker├─ dalvik.system.PathClassLoader instance 60*d9e8da70SAndroid Build Coastguard Worker``` 61*d9e8da70SAndroid Build Coastguard Worker 62*d9e8da70SAndroid Build Coastguard WorkerA line starting with `├─ ` represents a Java object (either a class, an object array or an instance), and a line starting with `│ ↓ ` represents a reference to the Java object on the next line. 63*d9e8da70SAndroid Build Coastguard Worker 64*d9e8da70SAndroid Build Coastguard Worker`PathClassLoader` has a `runtimeInternalObjects` field that is a reference to an array of `Object`: 65*d9e8da70SAndroid Build Coastguard Worker 66*d9e8da70SAndroid Build Coastguard Worker``` 67*d9e8da70SAndroid Build Coastguard Worker├─ dalvik.system.PathClassLoader instance 68*d9e8da70SAndroid Build Coastguard Worker│ ↓ PathClassLoader.runtimeInternalObjects 69*d9e8da70SAndroid Build Coastguard Worker├─ java.lang.Object[] array 70*d9e8da70SAndroid Build Coastguard Worker``` 71*d9e8da70SAndroid Build Coastguard Worker 72*d9e8da70SAndroid Build Coastguard WorkerThe element at position 43 in that array of `Object` is a reference to the `Utils` class. 73*d9e8da70SAndroid Build Coastguard Worker 74*d9e8da70SAndroid Build Coastguard Worker``` 75*d9e8da70SAndroid Build Coastguard Worker├─ java.lang.Object[] array 76*d9e8da70SAndroid Build Coastguard Worker│ ↓ Object[].[43] 77*d9e8da70SAndroid Build Coastguard Worker├─ com.example.Utils class 78*d9e8da70SAndroid Build Coastguard Worker``` 79*d9e8da70SAndroid Build Coastguard Worker 80*d9e8da70SAndroid Build Coastguard WorkerA line starting with `╰→ ` represents the leaking object, ie the object that is passed to [AppWatcher.objectWatcher.watch()](/leakcanary/api/leakcanary-object-watcher-android/leakcanary/-app-watcher/object-watcher/). 81*d9e8da70SAndroid Build Coastguard Worker 82*d9e8da70SAndroid Build Coastguard WorkerThe `Utils` class has a static `helper` field which is a reference to the leaking object, which is the Helper singleton instance: 83*d9e8da70SAndroid Build Coastguard Worker 84*d9e8da70SAndroid Build Coastguard Worker``` 85*d9e8da70SAndroid Build Coastguard Worker├─ com.example.Utils class 86*d9e8da70SAndroid Build Coastguard Worker│ ↓ static Utils.helper 87*d9e8da70SAndroid Build Coastguard Worker╰→ java.example.Helper instance 88*d9e8da70SAndroid Build Coastguard Worker``` 89*d9e8da70SAndroid Build Coastguard Worker 90*d9e8da70SAndroid Build Coastguard Worker## 2. Narrow down the suspect references 91*d9e8da70SAndroid Build Coastguard Worker 92*d9e8da70SAndroid Build Coastguard WorkerA leak trace is a path of references. Initially, all references in that path are suspected of causing the leak, but LeakCanary can automatically narrow down the suspect references. To understand what that means, let's go through that process manually. 93*d9e8da70SAndroid Build Coastguard Worker 94*d9e8da70SAndroid Build Coastguard WorkerHere's an example of bad Android code: 95*d9e8da70SAndroid Build Coastguard Worker 96*d9e8da70SAndroid Build Coastguard Worker```kotlin 97*d9e8da70SAndroid Build Coastguard Workerclass ExampleApplication : Application() { 98*d9e8da70SAndroid Build Coastguard Worker val leakedViews = mutableListOf<View>() 99*d9e8da70SAndroid Build Coastguard Worker} 100*d9e8da70SAndroid Build Coastguard Worker 101*d9e8da70SAndroid Build Coastguard Workerclass MainActivity : Activity() { 102*d9e8da70SAndroid Build Coastguard Worker override fun onCreate(savedInstanceState: Bundle?) { 103*d9e8da70SAndroid Build Coastguard Worker super.onCreate(savedInstanceState) 104*d9e8da70SAndroid Build Coastguard Worker setContentView(R.layout.main_activity) 105*d9e8da70SAndroid Build Coastguard Worker 106*d9e8da70SAndroid Build Coastguard Worker val textView = findViewById<View>(R.id.helper_text) 107*d9e8da70SAndroid Build Coastguard Worker 108*d9e8da70SAndroid Build Coastguard Worker val app = application as ExampleApplication 109*d9e8da70SAndroid Build Coastguard Worker // This creates a leak, What a Terrible Failure! 110*d9e8da70SAndroid Build Coastguard Worker app.leakedViews.add(textView) 111*d9e8da70SAndroid Build Coastguard Worker } 112*d9e8da70SAndroid Build Coastguard Worker} 113*d9e8da70SAndroid Build Coastguard Worker``` 114*d9e8da70SAndroid Build Coastguard Worker 115*d9e8da70SAndroid Build Coastguard WorkerLeakCanary produces a leak trace that looks like this: 116*d9e8da70SAndroid Build Coastguard Worker 117*d9e8da70SAndroid Build Coastguard Worker``` 118*d9e8da70SAndroid Build Coastguard Worker┬─── 119*d9e8da70SAndroid Build Coastguard Worker│ GC Root: System class 120*d9e8da70SAndroid Build Coastguard Worker│ 121*d9e8da70SAndroid Build Coastguard Worker├─ android.provider.FontsContract class 122*d9e8da70SAndroid Build Coastguard Worker│ ↓ static FontsContract.sContext 123*d9e8da70SAndroid Build Coastguard Worker├─ com.example.leakcanary.ExampleApplication instance 124*d9e8da70SAndroid Build Coastguard Worker│ ↓ ExampleApplication.leakedViews 125*d9e8da70SAndroid Build Coastguard Worker├─ java.util.ArrayList instance 126*d9e8da70SAndroid Build Coastguard Worker│ ↓ ArrayList.elementData 127*d9e8da70SAndroid Build Coastguard Worker├─ java.lang.Object[] array 128*d9e8da70SAndroid Build Coastguard Worker│ ↓ Object[].[0] 129*d9e8da70SAndroid Build Coastguard Worker├─ android.widget.TextView instance 130*d9e8da70SAndroid Build Coastguard Worker│ ↓ TextView.mContext 131*d9e8da70SAndroid Build Coastguard Worker╰→ com.example.leakcanary.MainActivity instance 132*d9e8da70SAndroid Build Coastguard Worker``` 133*d9e8da70SAndroid Build Coastguard Worker 134*d9e8da70SAndroid Build Coastguard WorkerHere's how to read that leak trace: 135*d9e8da70SAndroid Build Coastguard Worker 136*d9e8da70SAndroid Build Coastguard Worker> The `FontsContract` class is a system class (see `GC Root: System class`) and has an `sContext` static field which references an `ExampleApplication` instance which has a `leakedViews` field which references an `ArrayList` instance which references an array (the array backing the array list implementation) which has an element that references a `TextView` which has an `mContext` field which references a destroyed instance of `MainActivity`. 137*d9e8da70SAndroid Build Coastguard Worker 138*d9e8da70SAndroid Build Coastguard WorkerLeakCanary highlights all references suspected of causing this leak using ~~~ underlines. Initially, all references are suspect: 139*d9e8da70SAndroid Build Coastguard Worker 140*d9e8da70SAndroid Build Coastguard Worker``` 141*d9e8da70SAndroid Build Coastguard Worker┬─── 142*d9e8da70SAndroid Build Coastguard Worker│ GC Root: System class 143*d9e8da70SAndroid Build Coastguard Worker│ 144*d9e8da70SAndroid Build Coastguard Worker├─ android.provider.FontsContract class 145*d9e8da70SAndroid Build Coastguard Worker│ ↓ static FontsContract.sContext 146*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~ 147*d9e8da70SAndroid Build Coastguard Worker├─ com.example.leakcanary.ExampleApplication instance 148*d9e8da70SAndroid Build Coastguard Worker│ Leaking: NO (Application is a singleton) 149*d9e8da70SAndroid Build Coastguard Worker│ ↓ ExampleApplication.leakedViews 150*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~~~~ 151*d9e8da70SAndroid Build Coastguard Worker├─ java.util.ArrayList instance 152*d9e8da70SAndroid Build Coastguard Worker│ ↓ ArrayList.elementData 153*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~~~~ 154*d9e8da70SAndroid Build Coastguard Worker├─ java.lang.Object[] array 155*d9e8da70SAndroid Build Coastguard Worker│ ↓ Object[].[0] 156*d9e8da70SAndroid Build Coastguard Worker│ ~~~ 157*d9e8da70SAndroid Build Coastguard Worker├─ android.widget.TextView instance 158*d9e8da70SAndroid Build Coastguard Worker│ ↓ TextView.mContext 159*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~ 160*d9e8da70SAndroid Build Coastguard Worker╰→ com.example.leakcanary.MainActivity instance 161*d9e8da70SAndroid Build Coastguard Worker``` 162*d9e8da70SAndroid Build Coastguard Worker 163*d9e8da70SAndroid Build Coastguard WorkerThen, LeakCanary makes deductions about the **state** and the **lifecycle** of the objects in the leak trace. In an Android app the `Application` instance is a singleton that is never garbage collected, so it's never leaking (`Leaking: NO (Application is a singleton)`). From that, LeakCanary concludes that the leak is not caused by `FontsContract.sContext` (removal of corresponding `~~~`). Here's the updated leak trace: 164*d9e8da70SAndroid Build Coastguard Worker 165*d9e8da70SAndroid Build Coastguard Worker``` 166*d9e8da70SAndroid Build Coastguard Worker┬─── 167*d9e8da70SAndroid Build Coastguard Worker│ GC Root: System class 168*d9e8da70SAndroid Build Coastguard Worker│ 169*d9e8da70SAndroid Build Coastguard Worker├─ android.provider.FontsContract class 170*d9e8da70SAndroid Build Coastguard Worker│ ↓ static FontsContract.sContext 171*d9e8da70SAndroid Build Coastguard Worker├─ com.example.leakcanary.ExampleApplication instance 172*d9e8da70SAndroid Build Coastguard Worker│ Leaking: NO (Application is a singleton) 173*d9e8da70SAndroid Build Coastguard Worker│ ↓ ExampleApplication.leakedViews 174*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~~~~ 175*d9e8da70SAndroid Build Coastguard Worker├─ java.util.ArrayList instance 176*d9e8da70SAndroid Build Coastguard Worker│ ↓ ArrayList.elementData 177*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~~~~ 178*d9e8da70SAndroid Build Coastguard Worker├─ java.lang.Object[] array 179*d9e8da70SAndroid Build Coastguard Worker│ ↓ Object[].[0] 180*d9e8da70SAndroid Build Coastguard Worker│ ~~~ 181*d9e8da70SAndroid Build Coastguard Worker├─ android.widget.TextView instance 182*d9e8da70SAndroid Build Coastguard Worker│ ↓ TextView.mContext 183*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~ 184*d9e8da70SAndroid Build Coastguard Worker╰→ com.example.leakcanary.MainActivity instance 185*d9e8da70SAndroid Build Coastguard Worker``` 186*d9e8da70SAndroid Build Coastguard Worker 187*d9e8da70SAndroid Build Coastguard WorkerThe `TextView` instance references the destroyed `MainActivity` instance via it's `mContext` field. Views should not survive the lifecycle of their context, so LeakCanary knows that this `TextView` instance is leaking (`Leaking: YES (View.mContext references a destroyed activity)`), and therefore that the leak is not caused by `TextView.mContext` (removal of corresponding `~~~`). Here's the updated leak trace: 188*d9e8da70SAndroid Build Coastguard Worker 189*d9e8da70SAndroid Build Coastguard Worker``` 190*d9e8da70SAndroid Build Coastguard Worker┬─── 191*d9e8da70SAndroid Build Coastguard Worker│ GC Root: System class 192*d9e8da70SAndroid Build Coastguard Worker│ 193*d9e8da70SAndroid Build Coastguard Worker├─ android.provider.FontsContract class 194*d9e8da70SAndroid Build Coastguard Worker│ ↓ static FontsContract.sContext 195*d9e8da70SAndroid Build Coastguard Worker├─ com.example.leakcanary.ExampleApplication instance 196*d9e8da70SAndroid Build Coastguard Worker│ Leaking: NO (Application is a singleton) 197*d9e8da70SAndroid Build Coastguard Worker│ ↓ ExampleApplication.leakedViews 198*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~~~~ 199*d9e8da70SAndroid Build Coastguard Worker├─ java.util.ArrayList instance 200*d9e8da70SAndroid Build Coastguard Worker│ ↓ ArrayList.elementData 201*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~~~~ 202*d9e8da70SAndroid Build Coastguard Worker├─ java.lang.Object[] array 203*d9e8da70SAndroid Build Coastguard Worker│ ↓ Object[].[0] 204*d9e8da70SAndroid Build Coastguard Worker│ ~~~ 205*d9e8da70SAndroid Build Coastguard Worker├─ android.widget.TextView instance 206*d9e8da70SAndroid Build Coastguard Worker│ Leaking: YES (View.mContext references a destroyed activity) 207*d9e8da70SAndroid Build Coastguard Worker│ ↓ TextView.mContext 208*d9e8da70SAndroid Build Coastguard Worker╰→ com.example.leakcanary.MainActivity instance 209*d9e8da70SAndroid Build Coastguard Worker``` 210*d9e8da70SAndroid Build Coastguard Worker 211*d9e8da70SAndroid Build Coastguard WorkerTo summarize, LeakCanary inspects the state of objects in the leak trace to figure out if these objects are leaking (`Leaking: YES` vs `Leaking: NO`), and leverages that information to narrow down the suspect references. You can provide custom `ObjectInspector` implementations to improve how LeakCanary works in your codebase (see [Identifying leaking objects and labeling objects](recipes.md#identifying-leaking-objects-and-labeling-objects)). 212*d9e8da70SAndroid Build Coastguard Worker 213*d9e8da70SAndroid Build Coastguard Worker## 3. Find the reference causing the leak 214*d9e8da70SAndroid Build Coastguard Worker 215*d9e8da70SAndroid Build Coastguard WorkerIn the previous example, LeakCanary narrowed down the suspect references to `ExampleApplication.leakedViews`, `ArrayList.elementData` and `Object[].[0]`: 216*d9e8da70SAndroid Build Coastguard Worker 217*d9e8da70SAndroid Build Coastguard Worker``` 218*d9e8da70SAndroid Build Coastguard Worker┬─── 219*d9e8da70SAndroid Build Coastguard Worker│ GC Root: System class 220*d9e8da70SAndroid Build Coastguard Worker│ 221*d9e8da70SAndroid Build Coastguard Worker├─ android.provider.FontsContract class 222*d9e8da70SAndroid Build Coastguard Worker│ ↓ static FontsContract.sContext 223*d9e8da70SAndroid Build Coastguard Worker├─ com.example.leakcanary.ExampleApplication instance 224*d9e8da70SAndroid Build Coastguard Worker│ Leaking: NO (Application is a singleton) 225*d9e8da70SAndroid Build Coastguard Worker│ ↓ ExampleApplication.leakedViews 226*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~~~~ 227*d9e8da70SAndroid Build Coastguard Worker├─ java.util.ArrayList instance 228*d9e8da70SAndroid Build Coastguard Worker│ ↓ ArrayList.elementData 229*d9e8da70SAndroid Build Coastguard Worker│ ~~~~~~~~~~~ 230*d9e8da70SAndroid Build Coastguard Worker├─ java.lang.Object[] array 231*d9e8da70SAndroid Build Coastguard Worker│ ↓ Object[].[0] 232*d9e8da70SAndroid Build Coastguard Worker│ ~~~ 233*d9e8da70SAndroid Build Coastguard Worker├─ android.widget.TextView instance 234*d9e8da70SAndroid Build Coastguard Worker│ Leaking: YES (View.mContext references a destroyed activity) 235*d9e8da70SAndroid Build Coastguard Worker│ ↓ TextView.mContext 236*d9e8da70SAndroid Build Coastguard Worker╰→ com.example.leakcanary.MainActivity instance 237*d9e8da70SAndroid Build Coastguard Worker``` 238*d9e8da70SAndroid Build Coastguard Worker 239*d9e8da70SAndroid Build Coastguard Worker`ArrayList.elementData` and `Object[].[0]` are implementation details of `ArrayList`, and it's unlikely that there's a bug in the `ArrayList` implementation, so the reference causing the leak is the only remaining reference: `ExampleApplication.leakedViews`. 240*d9e8da70SAndroid Build Coastguard Worker 241*d9e8da70SAndroid Build Coastguard Worker## 4. Fix the leak 242*d9e8da70SAndroid Build Coastguard Worker 243*d9e8da70SAndroid Build Coastguard WorkerOnce you find the reference causing the leak, you need to figure out what that reference is about, when it should have been cleared and why it hasn't been. Sometimes it's obvious, like in the previous example. Sometimes you need more information to figure it out. You can [add labels](recipes.md#identifying-leaking-objects-and-labeling-objects), or explore the hprof directly (see [How can I dig beyond the leak trace?](faq.md#how-can-i-dig-beyond-the-leak-trace)). 244*d9e8da70SAndroid Build Coastguard Worker 245*d9e8da70SAndroid Build Coastguard Worker 246*d9e8da70SAndroid Build Coastguard Worker!!! warning 247*d9e8da70SAndroid Build Coastguard Worker Memory leaks cannot be fixed by replacing strong references with weak references. It's a common solution when attempting to quickly address memory issues, however it never works. The bugs that were causing references to be kept longer than necessary are still there. On top of that, it creates more bugs as some objects will now be garbage collected sooner than they should. It also makes the code much harder to maintain. 248*d9e8da70SAndroid Build Coastguard Worker 249*d9e8da70SAndroid Build Coastguard Worker 250*d9e8da70SAndroid Build Coastguard WorkerWhat's next? Customize LeakCanary to your needs with [code recipes](recipes.md)! 251