1A 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 3Follow these 4 steps to fix memory leaks: 4 51. Find the leak trace. 62. Narrow down the suspect references. 73. Find the reference causing the leak. 84. Fix the leak. 9 10LeakCanary helps you with the first two steps. The last two steps are up to you! 11 12## 1. Find the leak trace 13 14A **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 16For example, let's store a helper singleton in a static field: 17 18```java 19class Helper { 20} 21 22class Utils { 23 public static Helper helper = new Helper(); 24} 25``` 26 27Let's tell LeakCanary that the singleton instance is expected to be garbage collected: 28 29``` 30AppWatcher.objectWatcher.watch(Utils.helper) 31``` 32 33The leak trace for that singleton looks like this: 34 35``` 36┬─── 37│ GC Root: Local variable in native code 38│ 39├─ dalvik.system.PathClassLoader instance 40│ ↓ PathClassLoader.runtimeInternalObjects 41├─ java.lang.Object[] array 42│ ↓ Object[].[43] 43├─ com.example.Utils class 44│ ↓ static Utils.helper 45╰→ java.example.Helper 46``` 47 48Let'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 50* **Local variables**, which belong to the stack of a thread. 51* Instances of **active Java threads**. 52* **System Classes**, which never unload. 53* **Native references**, which are controlled by native code. 54 55``` 56┬─── 57│ GC Root: Local variable in native code 58│ 59├─ dalvik.system.PathClassLoader instance 60``` 61 62A 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 64`PathClassLoader` has a `runtimeInternalObjects` field that is a reference to an array of `Object`: 65 66``` 67├─ dalvik.system.PathClassLoader instance 68│ ↓ PathClassLoader.runtimeInternalObjects 69├─ java.lang.Object[] array 70``` 71 72The element at position 43 in that array of `Object` is a reference to the `Utils` class. 73 74``` 75├─ java.lang.Object[] array 76│ ↓ Object[].[43] 77├─ com.example.Utils class 78``` 79 80A 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 82The `Utils` class has a static `helper` field which is a reference to the leaking object, which is the Helper singleton instance: 83 84``` 85├─ com.example.Utils class 86│ ↓ static Utils.helper 87╰→ java.example.Helper instance 88``` 89 90## 2. Narrow down the suspect references 91 92A 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 94Here's an example of bad Android code: 95 96```kotlin 97class ExampleApplication : Application() { 98 val leakedViews = mutableListOf<View>() 99} 100 101class MainActivity : Activity() { 102 override fun onCreate(savedInstanceState: Bundle?) { 103 super.onCreate(savedInstanceState) 104 setContentView(R.layout.main_activity) 105 106 val textView = findViewById<View>(R.id.helper_text) 107 108 val app = application as ExampleApplication 109 // This creates a leak, What a Terrible Failure! 110 app.leakedViews.add(textView) 111 } 112} 113``` 114 115LeakCanary produces a leak trace that looks like this: 116 117``` 118┬─── 119│ GC Root: System class 120│ 121├─ android.provider.FontsContract class 122│ ↓ static FontsContract.sContext 123├─ com.example.leakcanary.ExampleApplication instance 124│ ↓ ExampleApplication.leakedViews 125├─ java.util.ArrayList instance 126│ ↓ ArrayList.elementData 127├─ java.lang.Object[] array 128│ ↓ Object[].[0] 129├─ android.widget.TextView instance 130│ ↓ TextView.mContext 131╰→ com.example.leakcanary.MainActivity instance 132``` 133 134Here's how to read that leak trace: 135 136> 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 138LeakCanary highlights all references suspected of causing this leak using ~~~ underlines. Initially, all references are suspect: 139 140``` 141┬─── 142│ GC Root: System class 143│ 144├─ android.provider.FontsContract class 145│ ↓ static FontsContract.sContext 146│ ~~~~~~~~ 147├─ com.example.leakcanary.ExampleApplication instance 148│ Leaking: NO (Application is a singleton) 149│ ↓ ExampleApplication.leakedViews 150│ ~~~~~~~~~~~ 151├─ java.util.ArrayList instance 152│ ↓ ArrayList.elementData 153│ ~~~~~~~~~~~ 154├─ java.lang.Object[] array 155│ ↓ Object[].[0] 156│ ~~~ 157├─ android.widget.TextView instance 158│ ↓ TextView.mContext 159│ ~~~~~~~~ 160╰→ com.example.leakcanary.MainActivity instance 161``` 162 163Then, 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 165``` 166┬─── 167│ GC Root: System class 168│ 169├─ android.provider.FontsContract class 170│ ↓ static FontsContract.sContext 171├─ com.example.leakcanary.ExampleApplication instance 172│ Leaking: NO (Application is a singleton) 173│ ↓ ExampleApplication.leakedViews 174│ ~~~~~~~~~~~ 175├─ java.util.ArrayList instance 176│ ↓ ArrayList.elementData 177│ ~~~~~~~~~~~ 178├─ java.lang.Object[] array 179│ ↓ Object[].[0] 180│ ~~~ 181├─ android.widget.TextView instance 182│ ↓ TextView.mContext 183│ ~~~~~~~~ 184╰→ com.example.leakcanary.MainActivity instance 185``` 186 187The `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 189``` 190┬─── 191│ GC Root: System class 192│ 193├─ android.provider.FontsContract class 194│ ↓ static FontsContract.sContext 195├─ com.example.leakcanary.ExampleApplication instance 196│ Leaking: NO (Application is a singleton) 197│ ↓ ExampleApplication.leakedViews 198│ ~~~~~~~~~~~ 199├─ java.util.ArrayList instance 200│ ↓ ArrayList.elementData 201│ ~~~~~~~~~~~ 202├─ java.lang.Object[] array 203│ ↓ Object[].[0] 204│ ~~~ 205├─ android.widget.TextView instance 206│ Leaking: YES (View.mContext references a destroyed activity) 207│ ↓ TextView.mContext 208╰→ com.example.leakcanary.MainActivity instance 209``` 210 211To 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 213## 3. Find the reference causing the leak 214 215In the previous example, LeakCanary narrowed down the suspect references to `ExampleApplication.leakedViews`, `ArrayList.elementData` and `Object[].[0]`: 216 217``` 218┬─── 219│ GC Root: System class 220│ 221├─ android.provider.FontsContract class 222│ ↓ static FontsContract.sContext 223├─ com.example.leakcanary.ExampleApplication instance 224│ Leaking: NO (Application is a singleton) 225│ ↓ ExampleApplication.leakedViews 226│ ~~~~~~~~~~~ 227├─ java.util.ArrayList instance 228│ ↓ ArrayList.elementData 229│ ~~~~~~~~~~~ 230├─ java.lang.Object[] array 231│ ↓ Object[].[0] 232│ ~~~ 233├─ android.widget.TextView instance 234│ Leaking: YES (View.mContext references a destroyed activity) 235│ ↓ TextView.mContext 236╰→ com.example.leakcanary.MainActivity instance 237``` 238 239`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 241## 4. Fix the leak 242 243Once 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 245 246!!! warning 247 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 249 250What's next? Customize LeakCanary to your needs with [code recipes](recipes.md)! 251