xref: /aosp_15_r20/external/leakcanary2/docs/changelog.md (revision d9e8da70d8c9df9a41d7848ae506fb3115cae6e6)
1
2# Change Log
3
4Please thank our [contributors](https://github.com/square/leakcanary/graphs/contributors) �� �� ��.
5
6I've started working on LeakCanary 3.0 so new 2.x releases only contain bug fixes and new known leak patterns.
7
8## Version 2.13 (2024-01-01)
9
10* �� [#2565](https://github.com/square/leakcanary/issues/2565) Fix AndroidX Fragments incorrectly marked as leaking if detached but not destroyed.
11* �� [#2568](https://github.com/square/leakcanary/issues/2568) Fixed missing `RECEIVER_EXPORTED` flag when calling `registerReceiver()` on API 34+.
12* �� [#2555](https://github.com/square/leakcanary/issues/2555) Binder stubs are now called out in leak traces.
13* �� [#2601](https://github.com/square/leakcanary/pull/2601) Added several known manufacturer & framework leaks.
14
15## Version 2.12 (2023-06-29)
16
17* �� [#2527](https://github.com/square/leakcanary/issues/2527) `LifecycleRegistry` in `androidx.lifecycle:lifecycle-runtime` was migrated to kotlin and its `mState` field name changed to `state` which broke LeakCanary expectations.
18* �� [#2545](https://github.com/square/leakcanary/pull/2545) Added several known manufacturer & framework leaks.
19
20
21## Version 2.11 (2023-05-17)
22
23* �� [#1764](https://github.com/square/leakcanary/issues/1764) Ignore phantom classes that were unloaded than reloaded (long time LeakCanary bug).
24* �� [#2471](https://github.com/square/leakcanary/issues/2471) Fix LeakCanary introducing a weird leak in Google's CI infra.
25* �� [#2496](https://github.com/square/leakcanary/issues/2496) Fix broken ViewModel leak detection
26
27## Version 2.10 (2022-11-10)
28
29### Experimental Neo4j heap dump exploration
30
31`shark-cli` has a new experiment `neo4j` command that will convert a heap dump into an embedded Neo4j database and then open Neo4j Browser to explore the heap dump.
32
33```
34brew install leakcanary-shark
35
36shark-cli --process com.example.app.debug neo4j
37```
38
39![Neo4J heap dump](https://user-images.githubusercontent.com/557033/200693468-aa783bb4-9a5a-4a41-8b92-582d44b31b92.png)
40
41### Other bug fixes and improvements ����
42
43* �� [#2440](https://github.com/square/leakcanary/pull/2440) Add Android 13 `POST_NOTICICATIONS` permission as well as a new `LeakCanary.Config.showNotifications` config to disable notifications entirely.
44* �� [#2416](https://github.com/square/leakcanary/pull/2416) Add Android 13 monochrome icon.
45* �� [#2371](https://github.com/square/leakcanary/issues/2371) Fix db crash when navigating heap dump screen.
46* �� [#2393](https://github.com/square/leakcanary/issues/2393) Allow LeakCanary to be defined as an AndroidX Startup dependency.
47* �� [#2430](https://github.com/square/leakcanary/issues/2430) Fix ShortcutManager crash on Android TV.
48* �� [#2382](https://github.com/square/leakcanary/issues/2382) Fix heap dump close crash.
49
50This list reflects only a subset of all changes. For more details, see the [2.10 Milestone](https://github.com/square/leakcanary/milestone/25) and the [full diff](https://github.com/square/leakcanary/compare/v2.9.1...v2.10).
51
52## Version 2.9.1 (2022-04-20)
53
54### Preface
55
56What are some things you'd like to see in a future LeakCanary 3 version? Tell me [on Twitter](https://twitter.com/Piwai)!
57
58Some ideas I'm playing with:
59
60* Moving heap analysis leak visualisation to a separate single app (written with Compose!) available on the PlayStore.
61* Bumping Okio to 3.0
62* Multiplatform heap analysis? Analyze a JVM heap dump in your browser?!
63* Visualize the heap dominators / retained size as a treemap.
64* A backend for LeakCanary?
65
66Anyway, that's still very much the future, let's talk about what's in `2.9.1` now!
67
68### New metrics in heap analysis metadata
69
70I built LeakCanary to help fix leaks, but in doing so I accidentally wrote a fairly flexible heap dump parser. Since we're parsing the heap to find leaks anyway, we might as well report additional interesting metrics. Here's what you'll now see in the heap dump metadata:
71
72* Class count: count of loaded classes
73* Instance count
74* Primitive array count
75* Object array count
76* Thread count
77* Heap total bytes
78* Bitmap count
79* Bitmap total bytes
80* Large bitmap count (bitmaps with more pixels than 1.1x the pixels on screen)
81* Large bitmap total bytes
82* SQLiteDatabase in memory (open or closed, as well as their file path)
83
84This is just a first pass, feedback and ideas welcome!
85
86### Performance improvements
87
88The heap analysis now traverses the heap dump using `RandomAccessFile` instead of `FileChannel.transferTo()` and is now 40% faster on API 23 and 20% faster on newer APIs.
89Also, sticky class GC roots are now deduplicated, which great reduces the memory footprint of LeakCanary on API 23 ([#2324](https://github.com/square/leakcanary/pull/2324)). You can read about the related investigation [on py.hashnode.dev](https://py.hashnode.dev/of-sharks-and-heaps-of-sticky-marshmallows).
90
91### Breaking change:  FailTestOnLeakRunListener deleted
92
93`FailTestOnLeakRunListener`, `FailTestOnLeak` and `FailAnnotatedTestOnLeakRunListener` were deprecated in LeakCanary 2.8 as they rely on hacking the Android Test library internals which have since changed, and have been replaced by `LeakAssertions.assertNoLeak()` and the `DetectLeaksAfterTestSuccess` test rule. I was initially planning of keep these around, but as I tried to increase API level coverage in LeakCanary I needed to upgrade the Android Test library to a more recent version, and the hacks now had compilation errors. So they're gone: [#2282](https://github.com/square/leakcanary/commit/7152d6e2f8bea866e3bd5397b882d5098bed7d8b). If you can't use the test rules just yet, you're welcome to copy paste the listener implementations in your own codebase.
94
95### Other bug fixes and improvements ����
96
97* �� [#2367](https://github.com/square/leakcanary/pull/2367) Fixed `AndroidLeakFixes.FLUSH_HANDLER_THREADS` (`HandlerThread` can have a null `Looper`).
98* �� [#2286](https://github.com/square/leakcanary/issues/2286) Update Curtains to include Proguard rules and prevent `WindowCallbackWrapper` crashes.
99* �� [#2294](https://github.com/square/leakcanary/issues/2294) Fixed `WindowDelegateCallback.onMenuOpened()` crash.
100* �� [#2328](https://github.com/square/leakcanary/pull/2328) Fixed ToastEventListener leak. Sorry ��!
101* �� [#2310](https://github.com/square/leakcanary/issues/2310) Fixed crash when using WorkManager < 2.1.0.
102* �� [#2342](https://github.com/square/leakcanary/issues/2342) Fixed crash when `HashSet.map` is null (which isn't supposed to happen, oh well, Android ��‍♂️).
103* �� [#2117](https://github.com/square/leakcanary/issues/2117) Fixed StrictMode disk read violations.
104* �� [#2351](https://github.com/square/leakcanary/pull/2351) Fixed a race causing a startup crash.
105* �� [#2315](https://github.com/square/leakcanary/issues/2315) Fixed crash when using Okio 1.14.
106* �� [#2182](https://github.com/square/leakcanary/issues/2182) Fixed multi rescheduling of `BackgroundListener$checkAppInBackground`.
107* �� [#2360](https://github.com/square/leakcanary/issues/2360) Fixed SQLiteOpenHelper concurrent creation crash.
108
109This list reflects only a subset of all changes. For more details, see the [2.9 Milestone](https://github.com/square/leakcanary/milestone/23) and the [full diff](https://github.com/square/leakcanary/compare/v2.8.1...v2.9.1).
110
111
112## Version 2.8.1 (2022-01-06)
113
114This is a bugfix release, a quick follow up to `2.8` which had a few major issues ��. If you haven't yet, you should definitely read the `2.8` changelog.
115
116### Thanks
117
118Please thank
119[@dicosta](https://github.com/dicosta),
120[@Goooler](https://github.com/Goooler),
121[@plnice](https://github.com/plnice),
122[@preetha1326](https://github.com/preetha1326)
123for their contributions, bug reports and feature requests �� �� ��.
124
125### Crash fixes ������
126
127This patch release fixes not 1, not 2, but 3 crashes!
128
129* �� [#2268](https://github.com/square/leakcanary/pull/2268) WorkManager expedited request crashes before API 31.
130* �� [#2270](https://github.com/square/leakcanary/issues/2270) Updating `LeakCanary.config` crashes when `AppWatcher` is not installed.
131* �� [#2271](https://github.com/square/leakcanary/issues/2271) Analysis failure on API 25 because `HashMap$Entry` became `HashMap$HashMapEntry` (on API 25) before it finally changed to `HashMap$Node`.
132
133For more details, see the [2.8.1 Milestone](https://github.com/square/leakcanary/milestone/24) and the [full diff](https://github.com/square/leakcanary/compare/v2.8...v2.8.1).
134
135## Version 2.8 (2022-01-04)
136
137Note: please update to `2.8.1` instead.
138
139### Preface
140
141The last release was 9 months ago. What happened?! Well, soon after releasing LeakCanary 2.7, I had my 2nd baby, a wonderful daughter ��. Having 2 young kids leaves a lot less time available for Open Source work... but it's worth it!
142
143― [P.Y.](https://twitter.com/Piwai)
144
145### Thanks
146
147Please thank
148[@aaronweihe](https://github.com/aaronweihe),
149[@alhah](https://github.com/alhah),
150[@Andre-max](https://github.com/Andre-max),
151[@AoraMD](https://github.com/AoraMD),
152[@BraisGabin](https://github.com/BraisGabin),
153[@breezenan](https://github.com/breezenan),
154[@Goooler](https://github.com/Goooler),
155[@iliaskomp](https://github.com/iliaskomp)
156[@Jeff11](https://github.com/Jeff11),
157[@jmnwong](https://github.com/jmnwong),
158[@IdioticMadman](https://github.com/IdioticMadman),
159[@keyur1sst](https://github.com/keyur1sst),
160[@lchen8](https://github.com/lchen8),
161[@leinardi](https://github.com/leinardi),
162[@Maragues](https://github.com/Maragues),
163[@mars885](https://github.com/mars885),
164[@mateuszkwiecinski](https://github.com/mateuszkwiecinski),
165[@matiash](https://github.com/matiash),
166[@maxxx](https://github.com/maxxx),
167[@preetha1326](https://github.com/preetha1326),
168[@SimonMarquis](https://github.com/SimonMarquis),
169[@slavonnet](https://github.com/slavonnet),
170[@Sonphil](https://github.com/Sonphil),
171[@summerlyr](https://github.com/summerlyr),
172[@SUPERCILEX](https://github.com/SUPERCILEX),
173[@utwyko](https://github.com/utwyko),
174[@ZacSweers](https://github.com/ZacSweers),
175[@ziranshang](https://github.com/ziranshang),
176[@zoltish](https://github.com/zoltish)
177for their contributions, bug reports and feature requests �� �� ��.
178
179### Improved support for data structure internals
180
181�� Inspired [by Android Studio](https://twitter.com/RalucaSauciuc/status/1343800565352996871), LeakCanary's node discovery during heap graph traversal is now abstracted away. This allows overlaying logical structure over common data structure internals.
182
183�� WHAT?!
184
185�� This means we can make known data structures look more like their APIs than their internals. For example, developers tend to think of setting a `HashMap` entry as `map["key"] = value` rather than `map.table[hash("key")].next.next.next = Node(value)`, which is what LeakCanary would previously show in its leak traces.
186
187Let's look at a `HashMap` example:
188
189```kotlin
190class CheckoutController {
191
192  val tabs = HashMap<String, Tab>()
193
194  fun addItemsTab(tab: Tab) {
195    tabs["ItemsTab"] = tab
196  }
197}
198```
199
200If the `Tab` instance holds on to a view, we might see a leak trace that would look like this:
201
202```
203│ ...
204├─ com.example.CheckoutController instance
205│    ↓ CheckoutController.tabs
206├─ java.util.HashMap instance
207│    ↓ HashMap.table
208├─ java.util.HashMap$Node[] array
209│    ↓ HashMap$Node[42]
210├─ java.util.HashMap$Node instance
211│    ↓ HashMap$Node.next
212├─ java.util.HashMap$Node instance
213│    ↓ HashMap$Node.value
214├─ com.example.Tab instance
215│ ...
216```
217
218With the improved data structure support, the leak trace is much clearer (also note how the `ItemsTab` string key is now surfaced):
219
220```
221│ ...
222├─ com.example.CheckoutController instance
223│    ↓ CheckoutController.tabs
224├─ java.util.HashMap instance
225│    ↓ HashMap[ItemsTab]
226├─ com.example.Tab instance
227│ ...
228```
229
230Another benefit of this change is that leak signatures become less dependent of the runtime, and therefore are more consistent. This is especially true for any data structure that relies on a linked list (`HashMap`, `LinkedList`, `MessageQueue`, ...). Currently LeakCanary supports a limited set of common data structures from Apache Harmony, Open JDK, and the Android SDK. Let me know what else you need!
231
232### ObjectAnimator leaks
233
234LeakCanary will now detect leaks that trigger when forgetting to cancel `ObjectAnimator`. This new feature is enabled by the node discovery changes described above!
235
236Let's say you accidentally start an infinite `ObjectAnimator` and never cancel it, like so:
237
238```kotlin
239class ExampleActivity : Activity() {
240
241  override fun onCreate(savedInstanceState: Bundle?) {
242    super.onCreate(savedInstanceState)
243    setContentView(R.layout.main_activity)
244    findViewById<Button>(R.id.button).setOnClickListener { view ->
245      ObjectAnimator.ofFloat(view, View.ALPHA, 0.1f, 0.2f).apply {
246        duration = 100
247        repeatMode = ValueAnimator.REVERSE
248        repeatCount = ValueAnimator.INFINITE
249        start()
250      }
251    }
252  }
253}
254```
255
256In previous releases, LeakCanary would detect that the animated view is leaking but it wouldn't be able to find the leak and instead would report it as an unreachable object: _An unreachable object is still in memory but LeakCanary could not find a strong reference path from GC roots._
257
258LeakCanary now reports the leak and adds animator state information, helping detect and fix any infinite `ObjectAnimator`.
259
260```
261┬───
262│ GC Root: Thread object
263264├─ java.lang.Thread instance
265│    Leaking: NO (the main thread always runs)
266│    Thread name: 'main'
267│    ↓ Thread.threadLocals
268│             ~~~~~~~~~~~~
269...
270├─ android.animation.ObjectAnimator instance
271│    Leaking: UNKNOWN
272│    mListeners = null
273│    mPropertyName = null
274mProperty.mName = alpha
275mProperty.mType = java.lang.Float
276│    mInitialized = true
277│    mStarted = true
278│    mRunning = true
279│    mAnimationEndRequested = false
280│    mDuration = 100
281│    mStartDelay = 0
282│    mRepeatCount = INFINITE (-1)
283│    mRepeatMode = REVERSE (2)
284│    ↓ ObjectAnimator.mTarget
285│                     ~~~~~~~
286╰→ android.widget.Button instance
287     Leaking: YES (View.mContext references a destroyed activity)
288```
289
290To learn more, see this AOSP issue: [ObjectAnimator.mTarget weak ref creates memory leaks on infinite animators](https://issuetracker.google.com/issues/212993949).
291
292### Leak detection in tests
293
294Previous releases of `leakcanary-android-instrumentation` introduced a `FailTestOnLeakRunListener` which could run leak detection after each UI tests. Unfortunately `FailTestOnLeakRunListener` relied on a hack around `androidx.test` internals to report failures. The internals keep changing with every `androidx.test` release and breaking `FailTestOnLeakRunListener` ��.
295
296`FailTestOnLeakRunListener` is now deprecated (��) and replaced by the `DetectLeaksAfterTestSuccess` test rule, which you can add to your test like any normal test rule.
297
298Additionally, you can call `LeakAssertions.assertNoLeak()` from anywhere in your instrumentation tests. You can also annotate tests with `@SkipLeakDetection` (for that to work you'll also need to set up the `TestDescriptionHolder` test rule).
299
300```kotlin
301class CartTest {
302  @get:Rule
303  val rules = RuleChain.outerRule(TestDescriptionHolder)
304    .around(DetectLeaksAfterTestSuccess())
305    .around(ActivityScenarioRule(CartActivity::class.java))
306
307  @Test
308  fun addItemToCart() {
309    // ...
310  }
311
312  @SkipLeakDetection("See #1234")
313  @Test
314  fun removeItemFromCart() {
315    // ...
316  }
317}
318```
319
320### Android 12
321
322Hopefully this time we fixed everything that Android 12 broke: missing `exported:true` tags, missing pending intent flags, and `ForegroundServiceStartNotAllowedException` crashes. If not, let us know! Can't wait for Android 13 to break everything again ��.
323
324### WorkManager
325
326Running an Android Service without crashing (`ForegroundServiceStartNotAllowedException`...) is becoming harder with every release of Android, so I got rid of the LeakCanary heap analyzer service! Instead, LeakCanary leverages WorkManager if you already have it as a dependency. If you don't use WorkManager, then LeakCanary will fall back to using a simple thread.
327
328Note: I recommend using at least [WorkManager 2.7.0](https://developer.android.com/jetpack/androidx/releases/work#2.7.0) as it adds the `WorkRequest.Builder.setExpedited()` API which LeakCanary leverages if available.
329
330### Multi process
331
332Switching to WorkManager also impacts the LeakCanary multi process approach, which now leverages WorkManager remote jobs. Blog on how I got this working: [WorkManager multi-process for libraries](https://py.hashnode.dev/workmanager-multi-process-for-libraries).
333
334Multi process is harder to get right so you should only use this if LeakCanary frequently runs out of memory while performing the heap analysis. Here are the updated set up steps:
335
3361) Add the `leakcanary-android-process` dependency and **keep the `leakcanary-android` dependency**.
337
338```groovy
339dependencies {
340  debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8'
341  debugImplementation 'com.squareup.leakcanary:leakcanary-android-process:2.8'
342}
343```
344
3452) Skip the initialization code in the `Application` class
346
347```kotlin
348class ExampleApplication : Application() {
349
350  override fun onCreate() {
351    if (LeakCanaryProcess.isInAnalyzerProcess(this)) {
352      return
353    }
354    super.onCreate()
355    // normal init goes here, skipped in :leakcanary process.
356  }
357}
358```
359
360That's it! Note that event listeners (see below) related to the analysis will fire in the remote process.
361
362### AndroidX App Startup
363
364LeakCanary now optionally supports the [AndroidX App Startup library](https://developer.android.com/topic/libraries/app-startup). All you need to do is replace the `leakcanary-android` dependency with `leakcanary-android-startup`:
365
366```groovy
367dependencies {
368  // Remove the normal leakcanary-android dependency
369  // debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8'
370  debugImplementation 'com.squareup.leakcanary:leakcanary-android-startup:2.8'
371}
372```
373
374Note 1: `leakcanary-android` adds the code for automatic installl to `leakcanary-android-core`. If you're calling `AppWatcher.manualInstall()`, you can depend directly on `leakcanary-android-core` instead of `leakcanary-android`, and you won't need the disable any automatic install.
375
376Note 2: the same principle applies to `leakcanary-object-watcher-android`: it depends on `leakcanary-object-watcher-android-core` and adds automatic install, while `leakcanary-object-watcher-android-startup` leverages the App Startup library. Same for `plumber-android`, `plumber-android-core` and  `plumber-android-startup`.
377
378### Event listeners
379
380`LeakCanary.Config` has a new `eventListeners` field allowing you to react to LeakCanary's lifecycle. If you want to customize this, you most likely should be keeping the default list of listeners and add or remove from it.
381
382For example, if you want to disable the LeakCanary toast:
383
384```kotlin
385LeakCanary.config = LeakCanary.config.run {
386  copy(
387    eventListeners = eventListeners.filter {
388      it !is ToastEventListener
389    }
390  )
391}
392```
393
394If you want to upload heap analysis results:
395
396```kotlin
397LeakCanary.config = LeakCanary.config.run {
398  copy(
399    eventListeners = eventListeners + EventListener { event ->
400      if (event is HeapAnalysisSucceeded) {
401        // Upload event.heapAnalysis
402      }
403    }
404  )
405}
406```
407
408Note: `Leakcanary.Config.onHeapAnalyzedListener` still works but is now deprecated.
409
410Feedback welcome on this new API!
411
412### Other bug fixes and improvements ����
413
414* [#2096](https://github.com/square/leakcanary/issues/2096) Opening / sharing heap dump files now supports LeakCanary as an option.
415* [#2210](https://github.com/square/leakcanary/issues/2210) First Compose dedicated object inspectors!
416* [#2121](https://github.com/square/leakcanary/pull/2121) Support for customizing the heap dumper.
417
418This list reflects only a subset of all changes. For more details, see the [2.8 Milestone](https://github.com/square/leakcanary/milestone/22) and the [full diff](https://github.com/square/leakcanary/compare/v2.7...v2.8).
419
420
421## Version 2.7 (2021-03-26)
422
423Please thank
424[@chao2zhang](https://github.com/chao2zhang),
425[@ihrupin](https://github.com/ihrupin),
426[@jzbrooks](https://github.com/jzbrooks),
427[@msfjarvis](https://github.com/msfjarvis),
428[@reneargento](https://github.com/reneargento),
429[@Unpublished](https://github.com/Unpublished)
430for their contributions, bug reports and feature requests �� �� ��.
431
432### Finer grained root view watching
433
434In version 2.6, LeakCanary added detection of root views retained after  `View.onDetachedFromWindow()`. This helps find more leaks, but unfortunately some Android widgets keep a detached root view around to reattach it later (e.g. spinner). App developers also sometimes do the same with dialogs, keeping a single instance around and calling `show()` and `hide()` as needed. As a result, LeakCanary would report leaks that were actually not leaks.
435
436In version 2.7, the default behavior changed: LeakCanary will continue to detect leaks of toasts, but will ignore root views created by a PopupWindow (which is what Android widgets use). It will also ignore root views created by a dialog by default, and you can turn this back on by setting the `leak_canary_watcher_watch_dismissed_dialogs` resource boolean to true:
437
438
439```xml
440<?xml version="1.0" encoding="utf-8"?>
441<resources>
442  <bool name="leak_canary_watcher_watch_dismissed_dialogs">true</bool>
443</resources>
444```
445
446This is implemented using a new Square library: [Curtains](https://github.com/square/curtains).
447
448### Targeting Android 12
449
450We fixed two issues for apps that want to target Android 12:
451
452* [#2074](https://github.com/square/leakcanary/pull/2074) Activities that use intent filters must declare the `android:exported` attribute.
453* [#2079](https://github.com/square/leakcanary/issues/2079) PendingIntent requires the `FLAG_IMMUTABLE` flag.
454
455### Bug fixes and improvements ����
456
457* [#2075](https://github.com/square/leakcanary/issues/2075) Fixed crash when sharing heap dumps.
458* [#2067](https://github.com/square/leakcanary/issues/2067) Fixed crash when opening leaks from older versions (before 2.6) of LeakCanary.
459* [#2049](https://github.com/square/leakcanary/issues/2049) Fixed Plumber crash due to R8 shaking AndroidLeakFixes.
460* [#2084](https://github.com/square/leakcanary/issues/2084) Fixed Shark crash when used from multiple threads.
461* [#2054](https://github.com/square/leakcanary/issues/2054) ������ Blocked Monkeys from deleting leaks.
462* [#2069](https://github.com/square/leakcanary/issues/2069) Added X button to the root leak activity (for custom devices with no back button)
463* [#2091](https://github.com/square/leakcanary/issues/2091) Added receiver details if LoadedApk shows up in the leaktrace.
464* [#2083](https://github.com/square/leakcanary/issues/2083) Added service status details (created or not) to leaktrace.
465* [#2099](https://github.com/square/leakcanary/pull/2099) Retry button if analysis fails.
466* [#2066](https://github.com/square/leakcanary/pull/2066) When heap analysis in UI tests is skipped and NoAnalysis is returned, NoAnalysis now includes a reason to help debug why it didn't run.
467* [#2000](https://github.com/square/leakcanary/issues/2000) The LeakCanary CI now leverages GitHub actions instead of Travis.
468
469For more details, see the [2.7 Milestone](https://github.com/square/leakcanary/milestone/21) and the [full diff](https://github.com/square/leakcanary/compare/v2.6...v2.7).
470
471##  Version 2.6 - Christmas Release �� (2020-12-24)
472
473Please thank
474[@chao2zhang](https://github.com/chao2zhang),
475[@ChaosLeung](https://github.com/ChaosLeung),
476[@LitterSun](https://github.com/LitterSun),
477[@mickverm](https://github.com/mickverm),
478[@opatry](https://github.com/opatry),
479[@Thomas-Vos](https://github.com/Thomas-Vos),
480[@tricknology](https://github.com/tricknology),
481[@rahul-a](https://github.com/rahul-a),
482[@samoylenkodmitry](https://github.com/samoylenkodmitry),
483[@sing0055](https://github.com/sing0055),
484[@ubiratansoares](https://github.com/ubiratansoares)
485for their contributions, bug reports and feature requests �� �� ��.
486
487This Christmas Release includes several external contributions and a bunch of cool new features! ����
488
489###  Detecting root views retained after `View.onDetachedFromWindow()`
490
491On Android, every displayed view hierarchy is attached to a window, whether it be the view hierarchy of an activity, a dialog, a toast or [a chat head](http://www.piwai.info/chatheads-basics). After a view hierarchy is detached from its window, it should be garbage collected.
492
493LeakCanary already detects leaks of activity view hierarchies because retained detached views reference their activity context and LeakCanary detects activities retained after `Activity.onDestroy()`. In this new release, LeakCanary will now detect the leak of a dialog view hierarchy as soon as that dialog is dismissed, or any other view that is passed to [WindowManager.removeView()](https://developer.android.com/reference/android/view/ViewManager#removeView(android.view.View)).
494
495###  Detecting services retained after `Service.onDestroy()`
496
497After an Android [service](https://developer.android.com/reference/android/app/Service) is destroyed, it should be garbage collected. Unfortunately, the Android SDK does not provide any generic API to observe the service lifecycle. We worked around that using reflection on greylist APIs (details in [#2014](https://github.com/square/leakcanary/pull/2014)). Let's hope this motivates the Android team to [build the APIs developers need](https://twitter.com/Piwai/status/1342029560116891648).
498
499### Configuring retained object detection
500
501With the detection of 2 new types of retained objects, we're also adding APIs to configure which _watchers_ should be installed as well as adding filtering capabilities.
502
503First, disable the automatic install:
504
505```xml
506<?xml version="1.0" encoding="utf-8"?>
507<resources>
508  <bool name="leak_canary_watcher_auto_install">false</bool>
509</resources>
510```
511
512Then you can install LeakCanary manually. LeakCanary 2.6 comes with 4 watchers installed by default: `ActivityWatcher`, `FragmentAndViewModelWatcher`, `RootViewWatcher`, `ServiceWatcher`. Here's an example to get all the default watchers except `ServiceWatcher`:
513
514```kotlin
515class DebugExampleApplication : ExampleApplication() {
516
517  override fun onCreate() {
518    super.onCreate()
519
520    val watchersToInstall = AppWatcher.appDefaultWatchers(application)
521      .filter { it !is ServiceWatcher }
522
523    AppWatcher.manualInstall(
524      application = application,
525      watchersToInstall = watchersToInstall
526    )
527  }
528}
529```
530
531LeakCanary introduces a new functional (SAM) interface implemented by `ObjectWatcher`: `ReachabilityWatcher`, with a `ReachabilityWatcher.expectWeaklyReachable()` method that replaces the now deprecated `ObjectWatcher.watch()` method. You can create the default watcher instances with a custom `ReachabilityWatcher` that delegates to `AppWatcher.objectWatcher` but filters out specific instances (e.g. `BadSdkLeakingFragment`):
532
533```kotlin
534class DebugExampleApplication : ExampleApplication() {
535
536  override fun onCreate() {
537    super.onCreate()
538
539    val delegate = ReachabilityWatcher { watchedObject, description ->
540      if (watchedObject !is BadSdkLeakingFragment) {
541        AppWatcher.objectWatcher.expectWeaklyReachable(watchedObject, description)
542      }
543    }
544
545    val watchersToInstall = AppWatcher.appDefaultWatchers(application, delegate)
546
547    AppWatcher.manualInstall(
548      application = application,
549      watchersToInstall = watchersToInstall
550    )
551  }
552}
553```
554
555With these new configuration options, `AppWatcher.config` is now deprecated and a no-op.
556
557### Dumping the heap on screen off
558
559The default threshold to dump the heap is **5 retained objects** when the app is **visible**, and **1 retained object** when the app is **not visible**. Up until now, visible meant "the app has at least one activity in **started** state". In LeakCanary 2.6, the app will now be considered **not visible** if the device screen is **off**, lowering the threshold to trigger heap dumps when you turn off the device screen.
560
561### LeakCanary for releases
562
563LeakCanary 2.6 introduces a new artifact: `leakcanary-android-release`. This artifact exposes APIs to run a heap analysis in release builds, in production.
564
565!!! danger
566    Everything about this is experimental. Running a heap analysis in production is not a very common thing to do, and we're still learning and experimenting with this. Also, both the artifact name and the APIs may change.
567
568```groovy
569dependencies {
570  // debugImplementation because LeakCanary should only run in debug builds.
571  debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.6'
572
573  // NEW: LeakCanary for releases!
574  releaseImplementation 'com.squareup.leakcanary:leakcanary-android-release:2.6'
575  // Optional: detect retained objects. This helps but is not required.
576  releaseImplementation 'com.squareup.leakcanary:leakcanary-object-watcher-android:2.6'
577}
578```
579
580Here's a code example that runs a heap analysis when the screen is turned off or the app enters background, checking first if a [Firebase Remote Config](https://firebase.google.com/products/remote-config) flag is turned on, and uploading the result to Bugsnag:
581
582
583```kotlin
584class ReleaseExampleApplication : ExampleApplication() {
585
586  // Cancels heap analysis if "heap_analysis_flag" is false.
587  private val flagInterceptor by lazy {
588    object : HeapAnalysisInterceptor {
589
590      val remoteConfig: FirebaseRemoteConfig = TODO()
591
592      override fun intercept(chain: Chain): HeapAnalysisJob.Result {
593        if (remoteConfig.getBoolean("heap_analysis_flag")) {
594          chain.job.cancel("heap_analysis_flag false")
595        }
596        return chain.proceed()
597      }
598    }
599  }
600
601  private val analysisClient by lazy {
602    HeapAnalysisClient(
603      // Use private app storage. cacheDir is never backed up which is important.
604      heapDumpDirectoryProvider = { cacheDir },
605      // stripHeapDump: remove all user data from hprof before analysis.
606      config = HeapAnalysisConfig(stripHeapDump = true),
607      // Default interceptors may cancel analysis for several other reasons.
608      interceptors = listOf(flagInterceptor) + HeapAnalysisClient.defaultInterceptors(this)
609    )
610  }
611
612  private val analysisExecutor by lazy {
613    Executors.newSingleThreadExecutor {
614      thread(start = false, name = "Heap analysis executor") {
615        android.os.Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND)
616        it.run()
617      }
618    }
619  }
620
621  private val analysisCallback: (Result) -> Unit by lazy {
622    val uploader = BugsnagHeapAnalysisUploader(this@ReleaseExampleApplication)
623    { result ->
624      if (result is Done) {
625        uploader.upload(result.analysis)
626	  }
627    }
628  }
629
630  override fun onCreate() {
631    super.onCreate()
632
633    // Delete any remaining heap dump (if we crashed)
634    analysisExecutor.execute {
635      analysisClient.deleteHeapDumpFiles()
636    }
637
638    // Starts heap analysis on background importance
639    BackgroundTrigger(
640      application = this,
641      analysisClient = analysisClient,
642      analysisExecutor = analysisExecutor,
643      analysisCallback = analysisCallback
644    ).start()
645
646    // Starts heap analysis when screen off
647    ScreenOffTrigger(
648      application = this,
649      analysisClient = analysisClient,
650      analysisExecutor = analysisExecutor,
651      analysisCallback = analysisCallback
652    ).start()
653  }
654
655  /**
656   * Call this to trigger heap analysis manually, e.g. from
657   * a help button.
658   *
659   * This method returns a `HeapAnalysisJob` on which you can
660   * call `HeapAnalysisJob.cancel()` at any time.
661   */
662  fun triggerHeapAnalysisNow(): HeapAnalysisJob {
663    val job = analysisClient.newJob()
664    analysisExecutor.execute {
665      val result = job.execute()
666      analysisCallback(result)
667    }
668    return job
669  }
670}
671```
672
673The Bugsnag uploader:
674
675```kotlin
676class BugsnagHeapAnalysisUploader(applicationContext: Application) {
677
678  private val bugsnagClient: Client
679
680  init {
681    bugsnagClient = Client(
682      applicationContext,
683      BUGSNAG_API_KEY,
684      DO_NOT_ENABLE_EXCEPTION_HANDLER
685    )
686    bugsnagClient.setSendThreads(false)
687  }
688
689  fun upload(heapAnalysis: HeapAnalysis) {
690    when (heapAnalysis) {
691      is HeapAnalysisSuccess -> {
692        val exception = HeapAnalysisReport()
693        bugsnagClient.notify(exception) { report ->
694          val metaData = report.error.metaData
695          metaData.addToTab("Heap Analysis", "result", heapAnalysis.toString())
696        }
697      }
698      is HeapAnalysisFailure -> {
699        // Please file any reported failure to
700        // https://github.com/square/leakcanary/issues
701        bugsnagClient.notify(heapAnalysis.exception)
702      }
703    }
704  }
705
706  // Exception with fake unique stacktrace to send all reports to the same error entry.
707  class HeapAnalysisReport : Exception("Check the HEAP ANALYSIS tab") {
708    override fun fillInStackTrace(): Throwable {
709      stackTrace = arrayOf(
710        StackTraceElement(
711          "HeapAnalysisReport",
712          "analyzeHeap",
713          "HeapAnalysisReport.kt",
714          1
715        )
716      )
717      return this
718    }
719  }
720
721  companion object {
722    private const val BUGSNAG_API_KEY = YOUR_BUGSNAG_API_KEY
723    private const val DO_NOT_ENABLE_EXCEPTION_HANDLER = false
724  }
725}
726```
727
728### More leak fixes in Plumber
729
730We added 3 new automatic fixes for known AOSP leaks in `plumber-android` (details: [#1993](https://github.com/square/leakcanary/issues/1993)). As a reminder, `plumber-android` is automatically included when you add `leakcanary-android`, and you can add it manually for build types that don't include LeakCanary:
731
732```gradle
733dependencies {
734  // leakcanary-android adds plumber-android to debug builds
735  debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.6'
736
737  // This adds plumber-android to all build types
738  implementation 'com.squareup.leakcanary:plumber-android:2.6'
739}
740```
741
742### Bug fixes and improvements ����
743
744* [#1948](https://github.com/square/leakcanary/pull/1948) Leakcanary is now compiled against Kotlin 1.4 (while staying 1.3 compatible) to support [Functional (SAM) interfaces](https://kotlinlang.org/docs/reference/fun-interfaces.html).
745* [#1956](https://github.com/square/leakcanary/issues/1956) The retained object size is displayed as a human readable output (KB, MB, ...).
746* [#1976](https://github.com/square/leakcanary/issues/1976) Improved default object inspectors and leak finders for `View` and `Context`.
747* [#1972](https://github.com/square/leakcanary/issues/1972) Fields are printed with the parent class name that holds the field in leak traces.
748* [#1981](https://github.com/square/leakcanary/issues/1981) Fixed StrictMode policy violation (main thread read from disk).
749* [#1977](https://github.com/square/leakcanary/issues/1977) Report objects that are not strongly reachable.
750* [#2018](https://github.com/square/leakcanary/pull/2018) & [#2019](https://github.com/square/leakcanary/pull/2019) Fixed crashes in LeakCanary UI (discovered by Monkey tests).
751* [#2015](https://github.com/square/leakcanary/issues/2015) Fixed crash on Android < 16.
752* [#2023](https://github.com/square/leakcanary/issues/2023) Fixed crash in plugin projects.
753
754For more details, see the [2.6 Milestone](https://github.com/square/leakcanary/milestone/20) and the [full diff](https://github.com/square/leakcanary/compare/v2.5...v2.6).
755
756## Version 2.5 (2020-10-01)
757
758Please thank
759[@Amokrane](https://github.com/Amokrane),
760[@Armaxis](https://github.com/Armaxis),
761[@askont](https://github.com/askont),
762[@chao2zhang](https://github.com/chao2zhang),
763[@daniil-shevtsov](https://github.com/daniil-shevtsov),
764[@eygraber](https://github.com/eygraber),
765[@msfjarvis](https://github.com/msfjarvis),
766[@mzgreen](https://github.com/mzgreen),
767[@lchen8](https://github.com/lchen8),
768[@rpattabi](https://github.com/rpattabi),
769[@sahil2441](https://github.com/sahil2441),
770[@SylvainGirod](https://github.com/SylvainGirod),
771[@vhow](https://github.com/vhow)
772for their contributions, bug reports and feature requests �� �� ��.
773
774### Heap analysis is twice as fast ����
775
776No one asked, so we delivered! We rewrote several core components in Shark (LeakCanary's heap analyzer) to dramatically reduce IO reads and allocations while keeping memory constant. More details on Twitter: [thread by @ArtemChubaryan](https://twitter.com/ArtemChubaryan/status/1311078061895553030) and [thread by @Piwai](https://twitter.com/Piwai/status/1311085280753926144).
777
778### Compute retained size within the leak trace
779
780Previously, LeakCanary computed the retained size for the leaking object (the last object in the leak trace). However, the bad reference causing objects to leak is often higher up in the leak trace and everything that it holds onto is actually leaking. So LeakCanary now computes the retained size for [all the objects in the leaktrace that have a LEAKING or UNKNOWN status](https://github.com/square/leakcanary/issues/1880):
781
782```
783┬───
784│ GC Root: System class
785786├─ com.example.MySingleton class
787│    Leaking: NO (a class is never leaking)
788│    ↓ static MySingleton.leakedView
789│                         ~~~~~~~~~~
790├─ android.widget.TextView instance
791│    Leaking: YES (View.mContext references a destroyed activity)
792│    Retaining 46326 bytes in 942 objects
793│    ↓ TextView.mContext
794╰→ com.example.MainActivity instance
795​     Leaking: YES (Activity#mDestroyed is true)
796​     Retaining 1432 bytes in 36 objects
797```
798
799### Disable LeakCanary from the UI
800
801New toggle to disable [heap dumping](https://github.com/square/leakcanary/issues/1886), which can be useful for QA, or when doing a product demo. LeakCanary will still show a notification when an object is retained.
802
803![disable heap dumping](images/disable_dumping.png)
804
805### Deobfuscating hprof files
806
807The [Shark CLI](shark.md#shark-cli) can now [deobfuscate heap dumps](https://github.com/square/leakcanary/issues/1698):
808
809```
810brew install leakcanary-shark
811
812shark-cli --hprof heapdump.hprof -m mapping.txt deobfuscate-hprof
813```
814
815### Bug fixes and improvements ����
816
817* Heap analysis text results now [wrap to a max width](https://github.com/square/leakcanary/issues/1811) when sharing them from the LeakCanary activity or printing to logcat. This will make it harder to miss details that are lost at the end of long lines of text.
818* The `leak_canary_watcher_auto_install`, `leak_canary_allow_in_non_debuggable_build` and `leak_canary_plumber_auto_install` resource booleans were [meant to be public](https://github.com/square/leakcanary/issues/1863).
819* We sprinkled a few `@JvmStatic` to [help Java consummers](https://github.com/square/leakcanary/issues/1870).
820* Fixed [crash when no browser installed](https://github.com/square/leakcanary/pull/1893).
821* Use distinct [group for LeakCanary notifications](https://github.com/square/leakcanary/issues/1845).
822* The heap analysis result now includes the [heap dump duration](https://github.com/square/leakcanary/pull/1931) because it looks like Android 11 heap dumps are [sometimes super slow](https://issuetracker.google.com/issues/168634429). We also added more [perf related metrics](https://github.com/square/leakcanary/issues/1929).
823* [Disable logging](https://github.com/square/leakcanary/issues/1910) when AppWatcher runs in release builds.
824* Highlight library leak patterns [directly within the leak traces](https://github.com/square/leakcanary/issues/1916).
825* Improved inspections for [Context, View](https://github.com/square/leakcanary/issues/1912) and [ContextImpl](https://github.com/square/leakcanary/pull/1884).
826
827
828For more details, see the [2.5 Milestone](https://github.com/square/leakcanary/milestone/19) and the [full diff](https://github.com/square/leakcanary/compare/v2.4...v2.5).
829
830
831## Version 2.4 (2020-06-10)
832
833Please thank
834[@0x109](https://github.com/0x109),
835[@andersu](https://github.com/andersu),
836[@antoniomerlin](https://github.com/antoniomerlin),
837[@bishiboosh](https://github.com/bishiboosh),
838[@ckesc](https://github.com/ckesc),
839[@jrodbx](https://github.com/jrodbx),
840[@LouisCAD](https://github.com/LouisCAD),
841[@marcardar](https://github.com/marcardar),
842[@OlivierGenez](https://github.com/OlivierGenez),
843[@pyricau](https://github.com/pyricau),
844[@runningcode](https://github.com/runningcode),
845[@seljad](https://github.com/seljad),
846[@worldsnas](https://github.com/worldsnas)
847for their contributions, bug reports and feature requests.
848
849### `plumber-android` is a new artifact that fixes known Android leaks ����
850
851LeakCanary reports all leaks, including leaks caused by a known bug in 3rd party code that you do not have control over (reported as [Library leaks](fundamentals-how-leakcanary-works.md#4-categorizing-leaks)). That can be annoying! LeakCanary now ships with a new dependency, `plumber-android`, which performs hacks at runtime to fix some of these known leaks. This releases has fixes for **11 known leaks**, but this is just the beginning. Contributions welcome! ��
852
853Note that since the `leakcanary-android` dependency is usually added as a `debugImplementation` dependency, the `plumber-android` is transitively added only in debug builds, so it will not fix leaks in your release builds. You can add the dependency directly as `implementation` to get these fixes in release builds as well:
854
855```groovy
856dependencies {
857  implementation 'com.squareup.leakcanary:plumber-android:2.4'
858}
859```
860
861!!! warning
862    While several of these fixes already ship in release builds of Square apps, this is the first official release of `plumber-android`, so you should consider it **experimental**.
863
864### Analyzing leaks from the CLI is easier than ever ��
865
866The [Shark CLI](shark.md#shark-cli) can now be installed via [Homebrew](https://brew.sh/)
867
868```
869brew install leakcanary-shark
870```
871
872You can then look for leaks in apps on any connected device, for example:
873
874```
875$ shark-cli --device emulator-5554 --process com.example.app.debug analyze
876```
877
878### Support for Android Test Orchestrator ��
879
880If you set up LeakCanary to report test failures when detecting leaks in instrumentation tests, it [now works](https://github.com/square/leakcanary/issues/1046) with Android Test Orchestrator as well. No change required, LeakCanary will automatically detect thatAndroid Test Orchestrator is running and hook into it.
881
882### No more `master` branch
883
884The branch name `master` comes from the *master / slave* terminology. We renamed the default branch to `main`, a small step towards making the LeakCanary community a safer space. Here's a good [thread on this topic](https://twitter.com/mislav/status/1270388510684598272).
885
886### Bug fixes and improvements ����
887
888* URLs in *Library Leak* descriptions are [now clickable](https://github.com/square/leakcanary/issues/1844)
889* Fixed [ordering issues](https://github.com/square/leakcanary/issues/1832) causing improper config with manual setup. A related change is that `AppWatcher.Config.enabled` is now deprecated.
890* Fixed possible [OutOfMemoryError failure](https://github.com/square/leakcanary/issues/1798) when computing retained size: we were loading to memory large arrays from the heap dump just to get their size.
891
892For more details, see the [2.4 Milestone](https://github.com/square/leakcanary/milestone/18) and the [full diff](https://github.com/square/leakcanary/compare/v2.3...v2.4).
893
894## Version 2.3 (2020-04-08)
895
896This is a minor release on the feature front, but a large release on the documentation front!
897
898Many thanks to
899[@adamfit](https://github.com/adamfit),
900[@Amokrane](https://github.com/Amokrane),
901[@Armaxis](https://github.com/Armaxis),
902[@artnc](https://github.com/artnc),
903[@burakeregar](https://github.com/burakeregar),
904[@ClaasJG](https://github.com/ClaasJG),
905[@clementcontet](https://github.com/clementcontet),
906[@ckesc](https://github.com/ckesc),
907[@cketti](https://github.com/cketti),
908[@fbenbassat](https://github.com/fbenbassat),
909[@Guneetgstar](https://github.com/Guneetgstar),
910[@Igorxp5](https://github.com/Igorxp5),
911[@JLLeitschuh](https://github.com/JLLeitschuh),
912[@KidAndroid](https://github.com/KidAndroid),
913[@ligi](https://github.com/ligi),
914[@mzgreen](https://github.com/mzgreen),
915[@pyricau](https://github.com/pyricau),
916[@sprintuu](https://github.com/sprintuu),
917[@tevjef](https://github.com/tevjef),
918[@thrlr123](https://github.com/thrlr123)
919for the contributions, bug reports and feature requests.
920
921We [asked for help](https://twitter.com/Piwai/status/1253454280758980609) and immediately started seeing more contributions. Thanks all! Check out the [How to help](how_to_help.md) page.
922
923### LeakCanary will now crash in release builds
924
925Despite the documentation insisting on using `debugImplementation`, we've seen apps [ship LeakCanary](https://twitter.com/Piwai/status/1245524534712602624) in **release builds**. Mistakes happen, so we've made that mistake [harder to miss](https://github.com/square/leakcanary/issues/1804) by making LeakCanary **crash when included in release builds**.
926
927Learn More: [LeakCanary in release builds](recipes.md#leakcanary-in-release-builds).
928
929### Doc site ����
930
931The doc site content has changed quite a bit! We applied advice from [Google's tech writing guide](https://developers.google.com/tech-writing/). If you've been confused by *Library Leaks* before, check out see the new [Categorizing leaks](fundamentals-how-leakcanary-works.md#4-categorizing-leaks) section. Take a look around, let us know what you think.
932
933### Bug fixes and improvements ��
934
935* The new [deobfuscation Gradle plugin](recipes.md#using-leakcanary-with-obfuscated-apps) wasn't working [with Gradle 3.6](https://github.com/square/leakcanary/issues/1761), this is now fixed. Also removed the requirement for the plugin to be [applied after AGP](https://github.com/square/leakcanary/pull/1816).
936* Fixed 2 crashes ([#1768](https://github.com/square/leakcanary/issues/1768) & [#1769](https://github.com/square/leakcanary/issues/1769)) in the LeakCanary UI found by a sneaky monkey runner ��.
937* The LeakCanary UI updates [immediately](https://github.com/square/leakcanary/issues/1742) when a heap analysis is added or deleted.
938* Fixed a crash when [updating from LeakCanary 2.0](https://github.com/square/leakcanary/pull/1800).
939* The *About* section of the LeakCanary now surfaces whether heap dumping is [currently enabled](https://github.com/square/leakcanary/issues/1803).
940* Fixed process [not exiting](https://github.com/square/leakcanary/issues/1711) in SharkCLI on Windows.
941* Improved [error message](https://github.com/square/leakcanary/pull/1823) when obfuscation mappings appear to be missing.
942
943For more details, see the [2.3 Milestone](https://github.com/square/leakcanary/milestone/17) and the [full diff](https://github.com/square/leakcanary/compare/v2.2...v2.3).
944
945## Version 2.2 (2020-02-05)
946
947We've got some good stuff for the first release of the decade!
948
949Many thanks to
950[@AndroidInternal](https://github.com/AndroidInternal),
951[@Armaxis](https://github.com/Armaxis),
952[@lic2050](https://github.com/lic2050),
953[@mzgreen](https://github.com/mzgreen),
954[@orenktaboola](https://github.com/orenktaboola),
955[@personshelldon](https://github.com/personshelldon),
956[@Plastix](https://github.com/Plastix),
957[@pyricau](https://github.com/pyricau)
958for the contributions, bug reports and feature requests.
959
960### ViewModel leak detection
961
962[Android ViewModels](https://developer.android.com/topic/libraries/architecture/viewmodel) are really cool! Their lifecycle is much nicer than fragments or activities, but sometimes mistakes happen. LeakCanary will now automatically detect ViewModel leaks and report any ViewModel instance retained after its `onCleared()` method was called.
963
964### Android TV
965
966![tv ui](images/android-tv-leaks.png)
967
968LeakCanary is finally coming to big screens near you! Best part - no additional setup is required, just enable it like you would for a [mobile device](getting_started.md). Now whenever there's a leak - you will see a helpful Toast appear with all the details. Make sure to check out our new [Android TV](recipes.md#android-tv) section and chill!
969
970### Java-friendly Config builders
971
972[It was brought to our attention](https://github.com/square/leakcanary/issues/1714) that configuring `LeakCanary` and `AppWatcher` was a miserable experience from Java code. Well, not anymore!
973
974Now you can use `LeakCanary.Config.Builder` and `AppWatcher.Config.Builder` to have idiomatic Java when updating the configurations. For example:
975
976```
977LeakCanary.Config config = LeakCanary.getConfig().newBuilder()
978  .retainedVisibleThreshold(3)
979  .computeRetainedHeapSize(false)
980  .build();
981LeakCanary.setConfig(config);
982```
983
984If you notice any other problems when using LeakCanary from Java, please [file an issue](https://github.com/square/leakcanary/issues/new?assignees=&labels=type%3A+enhancement&template=3-feature.md&title=)! We take Java-interop seriously and will be happy to improve LeakCanary's API!
985
986For more details, see the [2.2 Milestone](https://github.com/square/leakcanary/milestone/16) and the [full diff](https://github.com/square/leakcanary/compare/v2.1...v2.2).
987
988## Version 2.1 (2019-12-31)
989
990A special New Year's Eve release ��, the next release will be in another decade ��!
991
992Many thanks to
993[@adamfit](https://github.com/adamfit),
994[@alexander-smityuk](https://github.com/alexander-smityuk),
995[@Armaxis](https://github.com/Armaxis),
996[@BraisGabin](https://github.com/BraisGabin),
997[@devism](https://github.com/devism),
998[@ditclear](https://github.com/ditclear),
999[@jrodbx](https://github.com/jrodbx),
1000[@jstefanowski](https://github.com/jstefanowski),
1001[@Maragues](https://github.com/Maragues),
1002[@mzgreen](https://github.com/mzgreen),
1003[@pyricau](https://github.com/pyricau)
1004for the contributions, bug reports and feature requests.
1005
1006### A Gradle plugin for obfuscated apps
1007
1008It's fairly common for teams to have a QA build that is tested before making the release build. Usually that build will be obfuscated (via Proguard or R8), but also add LeakCanary to detect leaks during QA. This leads to obfuscated leak traces, which are hard to understand ��. Check out our new [Gradle deobfuscation plugin](recipes.md#using-leakcanary-with-obfuscated-apps) and rejoice!
1009
1010### UI <strike>twix</strike> tweaks
1011
1012In 2.0 we changed the LeakCanary UI and UX, and built a foundation on which 2.1 extends.
1013
1014![ui](images/screenshot-2.0.png)
1015
1016* Since 2.0, Leaks are grouped by their distinct signature. In 2.1 there's a `New` tag that will show until you open up a leak. There's also a `Library Leak` tag for leaks that are known to be caused by a bug in the Android Framework or Google libraries, and the library leak description now shows up in the UI.
1017* The type of the Java objects (class, instance, array) is now displayed in the LeakTrace, e.g. see `FontsContract class` and `ExampleApplication instance` above.
1018* The type of the GC root now shows up at the root of the leak trace. Makes sense!
1019* The leak result notification has an importance now set to MAX so that it'll show up right in your face. If you turn it off, the canary will haunt you in your dreams ����. To save your sanity and your device battery, automatic heap dumps now won't happen more often than once per minute.
1020* The resource id name for `View` instances is now displayed in the leak trace. You shouldn't look at the [implementation](https://github.com/square/leakcanary/pull/1663).
1021
1022```
1023├─ android.widget.TextView instance
1024View.mID = R.id.helper_text
1025```
1026
1027### Documentation goodies
1028
1029* The [Fundamentals](fundamentals.md) page was entirely rewritten, split into 3 pages and moved to its own tab. Please read it and provide feedback!
1030* At Square, we have been uploading leaks to Bugsnag for 3 years now, so that no leak ever gets missed. Follow [this recipe](uploading.md)!
1031* Did you know you can [run LeakCanary in a JVM](recipes.md#detecting-leaks-in-jvm-applications)?
1032
1033### API <strike>breaking</strike> bettering changes
1034
1035* The APIs of the `Leak` and `LeakTrace` classes have significantly changed, e.g. all `LeakTrace` instances with an identical signature are grouped under the same Leak object. Despite these breaking changes, this release version is a minor update. Oh noes, what about semantic versioning ��? Ask Don Quixote.
1036* You can now customize the way LeakCanary finds the leaking objects in the heap dump. For example, here's the configuration SharkCli uses to find leaks in heap dumps of apps that don't even have the LeakCanary dependency:
1037
1038```kotlin
1039LeakCanary.config = LeakCanary.config.copy(
1040    leakingObjectFinder = FilteringLeakingObjectFinder(
1041        AndroidObjectInspectors.appLeakingObjectFilters
1042    )
1043)
1044```
1045
1046* LeakCanary automatically disables itself in tests by detecting that the `org.junit.Test` is in the classpath. Unfortunately, some apps ship Junit in their app debug classpath (e.g. when using OkHttp MockWebServer). You can now customize which class is used to detect tests:
1047
1048```xml
1049<resources>
1050  <string name="leak_canary_test_class_name">assertk.Assert</string>
1051</resources>
1052```
1053
1054### Interactive CLI
1055
1056[Shark CLI](https://github.com/square/leakcanary/releases/download/v2.1/shark-cli-2.1.zip) was rewritten on top of [Clikt](https://github.com/ajalt/clikt):
1057
1058```bash
1059$ shark-cli
1060Usage: shark-cli [OPTIONS] COMMAND [ARGS]...
1061
1062                 ^`.                 .=""=.
1063 ^_              \  \               / _  _ \
1064 \ \             {   \             |  d  b  |
1065 {  \           /     `~~~--__     \   /\   /
1066 {   \___----~~'              `~~-_/'-=\/=-'\,
1067  \                         /// a  `~.      \ \
1068  / /~~~~-, ,__.    ,      ///  __,,,,)      \ |
1069  \/      \/    `~~~;   ,---~~-_`/ \        / \/
1070                   /   /            '.    .'
1071                  '._.'             _|`~~`|_
1072                                    /|\  /|\
1073
1074Options:
1075  -p, --process NAME              Full or partial name of a process, e.g.
1076                                  "example" would match "com.example.app"
1077  -d, --device ID                 device/emulator id
1078  -m, --obfuscation-mapping PATH  path to obfuscation mapping file
1079  --verbose / --no-verbose        provide additional details as to what
1080                                  shark-cli is doing
1081  -h, --hprof FILE                path to a .hprof file
1082  --help                          Show this message and exit
1083
1084Commands:
1085  interactive   Explore a heap dump.
1086  analyze       Analyze a heap dump.
1087  dump-process  Dump the heap and pull the hprof file.
1088  strip-hprof   Replace all primitive arrays from the provided heap dump with
1089                arrays of zeroes and generate a new "-stripped.hprof" file.
1090```
1091
1092There's a new `interactive` command which enables exploring the heap dump from the command line:
1093
1094```bash
1095$ shark-cli -h heapdump.hprof interactive
1096Enter command [help]:
1097help
1098
1099Available commands:
1100  analyze                   Analyze the heap dump.
1101  class NAME@ID             Show class with a matching NAME and Object ID.
1102  instance CLASS_NAME@ID    Show instance with a matching CLASS_NAME and Object
1103ID.
1104  array CLASS_NAME@ID       Show array instance with a matching CLASS_NAME and
1105Object ID.
1106  ->instance CLASS_NAME@ID  Show path from GC Roots to instance.
1107  ~>instance CLASS_NAME@ID  Show path from GC Roots to instance, highlighting
1108suspect references.
1109  help                      Show this message.
1110  exit                      Exit this interactive prompt.
1111```
1112
1113We're currently exploring the idea of adding [support for SQL queries](https://twitter.com/Piwai/status/1211795647273160704), feedback welcome!
1114
1115For more details, see the [2.1 Milestone](https://github.com/square/leakcanary/milestone/15) and the [full diff](https://github.com/square/leakcanary/compare/v2.0...v2.1).
1116
1117## Version 2.0 (2019-11-27)
1118
1119In the past 7 months, LeakCanary went through 3 alphas and 5 betas, encompassing 23 contributors over 493 commits, 35826 insertions and 10156 deletions.
1120
1121### Should I upgrade?
1122
1123**YES!** LeakCanary 2 is so much better, it might make you excited when you see a new memory leak. Follow the [upgrade guide](upgrading-to-leakcanary-2.0.md), you won't regret it!
1124
1125### So, what's changed since 1.6.3?
1126
1127**Everything.** The LeakCanary codebase went from **~6000** lines of Java to **~16000** lines of Kotlin, excluding comments & blanks.
1128
1129!!! question "Isn't Kotlin supposed to drastically reduce the amount of boilerplate code?"
1130    Absolutely! And it did. But then, we wrote more code.
1131    LeakCanary used to depend on [HAHA](https://github.com/square/haha), a repackaging of [perflib](https://android.googlesource.com/platform/tools/base/+/2f03004c181baf9d291a9bf992e1b444e83cd82d/perflib/), the heap dump parser used by Android Studio. Unfortunately perflib was slow and used too much memory, so LeakCanary now includes its own heap dump parser: [Shark](shark.md). The extra code comes from Shark, but also from having a lot more automated tests, and an improved UI layer.
1132
1133One major difference: when the app is in foreground, LeakCanary 2 will not trigger on every retained instance. Instead it will wait until the app goes in background or to reach a threashold of 5 retained instances in foreground. The analysis will then find all the leaks at once, and group identical leaks in the results UI. Please read the [Fundamentals](fundamentals.md) section to learn more!
1134
1135### Random facts
1136
1137* You can customize the Leaks launcher icon and label: [learn more here](recipes.md#icon-and-label).
1138* If you ` press on your main activity launcher icon, you should see a LeakCanary dynamic shortcut. You can then long press that to drop it on your home screen, and the launcher shows that it's the leaks launcher for your app.
1139* Out of the box, LeakCanary tracks all fragments flavors: AOSP, Support Library and Android X.
1140* From within the leak screen, you can share a leak to stack overflow. You can also share a heap dump, or import and analyze a heap dump from another device.
1141* You can run LeakCanary from your computer command line, on any debuggable app even if that app doesn't have LeakCanary: [learn more here](shark.md##shark-cli).
1142* The new documentation is fully searchable and includes the API documentation. Try the search bar ⤴.
1143* A large 160Mb heap dump uses 2Gb memory when opening it in Android Studio, but only 40Mb with Shark.
1144
1145### Changes since 2.0 Beta 5
1146
1147* Shark CLI supports multiple connected devices [#1642](https://github.com/square/leakcanary/issues/1642)
1148* Fixed missing sources from Maven Central [#1643](https://github.com/square/leakcanary/issues/1643)
1149* Updated notification icon to avoid confusion with Twitter DM notifications, and added icons to bottom navigation bar [#1648](https://github.com/square/leakcanary/pull/1648)
1150* Automatic leak detection for support library fragments [#1611](https://github.com/square/leakcanary/pull/1611)
1151
1152Many thanks to
1153[@AndreasBoehm](https://github.com/AndreasBoehm),
1154[@jrodbx](https://github.com/jrodbx),
1155[@pyricau](https://github.com/pyricau)
1156for the contributions, bug reports and feature requests.
1157
1158For more details, see the [2.0 Milestone](https://github.com/square/leakcanary/milestone/14) and the [full diff](https://github.com/square/leakcanary/compare/v2.0-beta-5...v2.0).
1159
1160## Version 2.0 Beta 5 (2019-11-25)
1161
1162* Major bugfix: native gc roots were accidentally ignored in Beta 4, as a result some leaks were not found [#1634](https://github.com/square/leakcanary/issues/1634)
1163* Fixed Lint warning (`leak_canary_about_message` string triggered *multiple substitutions* warning) [#1630](https://github.com/square/leakcanary/issues/1630)
1164
1165Many thanks to
1166[@DanEdgarTarget](https://github.com/DanEdgarTarget),
1167[@msfjarvis](https://github.com/msfjarvis),
1168[@PaulWoitaschek](https://github.com/pyricau),
1169[@pyricau](https://github.com/pyricau),
1170[@ZacSweers](https://github.com/ZacSweers)
1171for the contributions, bug reports and feature requests.
1172
1173For more details, see the [2.0-beta-5 Milestone](https://github.com/square/leakcanary/milestone/13) and the [full diff](https://github.com/square/leakcanary/compare/v2.0-beta-4...v2.0-beta-5).
1174
1175## Version 2.0 Beta 4 (2019-11-18)
1176
1177* Improved string rendering for heap analysis results
1178* UX redesign [#1445](https://github.com/square/leakcanary/issues/1445)
1179* Support for pattern matching of native reference leaks [#1562](https://github.com/square/leakcanary/issues/1562)
1180* Added support for deobfuscation using Proguard mapping files in Shark [#1499](https://github.com/square/leakcanary/issues/1499). This isn't directly supported in LeakCanary yet.
1181* Added support for extracting metadata from the heap dump (see the [recipe](recipes.md#extracting-metadata-from-the-heap-dump)) [#1519](https://github.com/square/leakcanary/issues/1519)
1182* Improved auto disabling of LeakCanary in Unit and UI tests [#1552](https://github.com/square/leakcanary/issues/1552)
1183* Several performance improvements when parsing heap dumps
1184* Fixed several bugs and crashes
1185* Added new known leak patterns
1186
1187Many thanks to
1188[@Armaxis](https://github.com/Armaxis),
1189[@BraisGabin](https://github.com/BraisGabin),
1190[@bric3](https://github.com/bric3),
1191[@elihart](https://github.com/elihart),
1192[@fernandospr](https://github.com/fernandospr),
1193[@flickator](https://github.com/flickator),
1194[@gabrysgab](https://github.com/gabrysgab),
1195[@JorgeDLS](https://github.com/JorgeDLS),
1196[@lannyf77](https://github.com/lannyf77),
1197[@msfjarvis](https://github.com/msfjarvis),
1198[@mzgreen](https://github.com/mzgreen),
1199[@ozmium](https://github.com/ozmium),
1200[@PaulWoitaschek](https://github.com/pyricau),
1201[@pyricau](https://github.com/pyricau),
1202[@shelpy](https://github.com/shelpy),
1203[@vRallev](https://github.com/vRallev),
1204[@ZacSweers](https://github.com/ZacSweers)
1205for the contributions, bug reports and feature requests.
1206
1207For more details, see the [2.0-beta-4 Milestone](https://github.com/square/leakcanary/milestone/12) and the [full diff](https://github.com/square/leakcanary/compare/v2.0-beta-3...v2.0-beta-4).
1208
1209## Version 2.0 Beta 3 (2019-08-22)
1210
1211* Baseline memory usage for large hprofs divided by 3 and removed memory spikes [#1543](https://github.com/square/leakcanary/pull/1543)
1212* Fixed crash when LeakCanary is initialized from another process [#1529](https://github.com/square/leakcanary/issues/1529)
1213* Java local references are deprioritized to look for longer alternative paths [#1525](https://github.com/square/leakcanary/pull/1525)
1214* Fixed `JavaLocalPattern` not matching on Lollipop [#1524](https://github.com/square/leakcanary/pull/1524)
1215
1216Many thanks to
1217[@Armaxis](https://github.com/Armaxis),
1218[@elihart](https://github.com/elihart),
1219[@emartynov](https://github.com/emartynov),
1220[@hmcgreevy-instil](https://github.com/hmcgreevy-instil),
1221[@pyricau](https://github.com/pyricau)
1222for the contributions, bug reports and feature requests.
1223
1224For more details, see the [2.0-beta-3 Milestone](https://github.com/square/leakcanary/milestone/11) and the [full diff](https://github.com/square/leakcanary/compare/v2.0-beta-2...v2.0-beta-3).
1225
1226## Version 2.0 Beta 2 (2019-08-02)
1227
1228* Fixed *Leak analysis failed: Object id not found in heap dump.* [#1516](https://github.com/square/leakcanary/issues/1516)
1229* 10x speed increase of hprof indexing on large heap dumps [#1520](https://github.com/square/leakcanary/pull/1520)
1230
1231Many thanks to
1232[@kolphi](https://github.com/kolphi),
1233[@pyricau](https://github.com/pyricau),
1234[@ZacSweers](https://github.com/ZacSweers)
1235for the contributions, bug reports and feature requests.
1236
1237For more details, see the [2.0-beta-2 Milestone](https://github.com/square/leakcanary/milestone/10) and the [full diff](https://github.com/square/leakcanary/compare/v2.0-beta-1...v2.0-beta-2).
1238
1239## Version 2.0 Beta 1 (2019-07-30)
1240
1241* New standalone library! [Shark](shark.md) is the heap analyzer that powers LeakCanary 2, and it can run in any Java VM. It comes with a [CLI](shark.md#shark-cli): you can now run `shark-cli analyze-process com.example.myapp` from your computer.
1242* New Heap Explorer directly on device! Open a Heap Analysis in LeakCanary, tap the options menu and select "Heap Explorer". This is still experimental and not very user friendly, contributions welcome!
1243* **Large API rewrite** to improve usability. If you used the alpha with a customized configuration, there are breaking changes. Of note: LeakSentry became [AppWatcher](/leakcanary/api/leakcanary-object-watcher-android/leakcanary/-app-watcher/), RefWatcher became [ObjectWatcher](/leakcanary/api/leakcanary-object-watcher/leakcanary/-object-watcher/), AndroidExcludedRefs became [AndroidReferenceMatchers](/leakcanary/api/shark-android/shark/-android-reference-matchers/), AnalysisResultListener became [OnHeapAnalyzedListener](/leakcanary/api/leakcanary-android-core/leakcanary/-on-heap-analyzed-listener/), AndroidLeakTraceInspectors became [AndroidObjectInspectors](/leakcanary/api/shark-android/shark/-android-object-inspectors/).
1244* The entire API surface is now documented and the documentation is available on this website: see the **LeakCanary API** tab at the top.
1245* Removed the **dependency on Android X**. No more configuration issues! [#1462](https://github.com/square/leakcanary/issues/1462)
1246* Added **Proguard rules** for LeakCanary and ObjectWatcher. [#1500](https://github.com/square/leakcanary/pull/1500)
1247* Display LeakCanary version in the About screen. [#1448](https://github.com/square/leakcanary/issues/1448)
1248* Bug fixes, new reference matchers and object inspectors
1249
1250Many thanks to
1251[@arctouch-carlosottoboni](https://github.com/arctouch-carlosottoboni),
1252[@jemaystermind](https://github.com/jemaystermind),
1253[@kushagrakumar27](https://github.com/kushagrakumar27),
1254[@pyricau](https://github.com/pyricau),
1255[@snkashis](https://github.com/snkashis)
1256for the contributions, bug reports and feature requests.
1257
1258For more details, see the [2.0-beta-1 Milestone](https://github.com/square/leakcanary/milestone/9) and the [full diff](https://github.com/square/leakcanary/compare/v2.0-alpha-3...v2.0-beta-1).
1259
1260## Version 2.0 Alpha 3 (2019-07-04)
1261
1262* [#1401](https://github.com/square/leakcanary/pull/1401) LeakCanary can now import all hprof files created from prior LeakCanary versions.
1263* [#1414](https://github.com/square/leakcanary/pull/1414) New API: `RefWatcher.retainedInstances` which returns the instances that are currently considered retained.
1264* [#1419](https://github.com/square/leakcanary/pull/1419) New APIs: `LeakCanary.Config.maxStoredHeapDumps` (default 7) and `LeakCanary.Config.requestWriteExternalStoragePermission` (default false). LeakCanary won't ask for the external storage permission anymore by default.
1265* [#1338](https://github.com/square/leakcanary/issues/1338) API change: `LeakCanary.Config.exclusionsFactory` replaced with `LeakCanary.Config.knownReferences` (simpler use), `LeakCanary.Config.leakInspectors` and `LeakCanary.Config.labelers` merged into `LeakCanary.Config.leakTraceInspectors` which provides access to the entire leak trace as well as a new graph oriented API that replaces the low level hprof parser API.
1266* [#1382](https://github.com/square/leakcanary/issues/1382) LeakCanary now disables automatic heap dumping when running in AndroidX UI tests.
1267* [#1424](https://github.com/square/leakcanary/pull/1424) API rename: `RefWatcher.hasRetainedReferences` => `RefWatcher.hasRetainedInstances`, `RefWatcher.retainedReferenceCount` => `RefWatcher.retainedInstanceCount`, `RefWatcher.hasWatchedReferences` => `RefWatcher.hasWatchedInstances`, `RefWatcher.removeKeysRetainedBeforeHeapDump` => `RefWatcher.removeInstancesRetainedBeforeHeapDump`, `RefWatcher.clearWatchedReferences` => `RefWatcher.clearWatchedInstances`.
1268* [#1432](https://github.com/square/leakcanary/pull/1432) [#1438](https://github.com/square/leakcanary/pull/1438) [#1440](https://github.com/square/leakcanary/pull/1440) New "won't fix" leaks and leak trace inspectors
1269* [#1374](https://github.com/square/leakcanary/issues/1374) [#1364](https://github.com/square/leakcanary/issues/1364) [#1366](https://github.com/square/leakcanary/issues/1366) [#1417](https://github.com/square/leakcanary/issues/1417) [#1399](https://github.com/square/leakcanary/issues/#1399) [#1416](https://github.com/square/leakcanary/issues/1416) [#1407](https://github.com/square/leakcanary/issues/1407) [#1427](https://github.com/square/leakcanary/issues/1427) [#1385](https://github.com/square/leakcanary/issues/1385) Bug and crash fixes
1270
1271Many thanks to
1272[@1step2hell](https://github.com/1step2hell),
1273[@afollestad](https://github.com/afollestad),
1274[@ansman](https://github.com/ansman),
1275[@bjdodson](https://github.com/bjdodson),
1276[@BraisGabin](https://github.com/BraisGabin),
1277[@EBfVince](https://github.com/EBfVince),
1278[@jaredsburrows](https://github.com/jaredsburrows),
1279[@pforhan](https://github.com/pforhan),
1280[@pyricau](https://github.com/pyricau),
1281[@tellypresence](https://github.com/tellypresence),
1282[@wiyarmir](https://github.com/wiyarmir)
1283for the contributions, bug reports and feature requests.
1284
1285For more details, see the [2.0-alpha-3 Milestone](https://github.com/square/leakcanary/milestone/8) and the [full diff](https://github.com/square/leakcanary/compare/v2.0-alpha-2...v2.0-alpha-3).
1286
1287## Version 2.0 Alpha 2 (2019-05-21)
1288
1289* [#1040](https://github.com/square/leakcanary/pull/1040) Import and analyze hprof files from other devices
1290* [#1344](https://github.com/square/leakcanary/pull/1344) Computing retained size
1291* [#1325](https://github.com/square/leakcanary/pull/1325) New notification showing current count of retained instances
1292* [#1079](https://github.com/square/leakcanary/pull/1079) "Excluded" leaks have been renamed to "Won't fix" leaks to clarify meaning.
1293* [#1328](https://github.com/square/leakcanary/pull/1328) New leaks are called out in the UI.
1294* [#1327](https://github.com/square/leakcanary/pull/1327) LeakSentry can be enabled / disabled and is automatically disabled in non debuggable builds.
1295* [#1173](https://github.com/square/leakcanary/pull/1173) Experimental: now reporting leaks that only go through weak references (previously reported as "no path to instance")
1296* [#1339](https://github.com/square/leakcanary/pull/1339) Readded support for Thread name based exclusions
1297* [#1312](https://github.com/square/leakcanary/pull/1312) Fixed bug causing LeakCanary to stop detecting leaks after the app is killed.
1298* [#1310](https://github.com/square/leakcanary/pull/1310) [#1313](https://github.com/square/leakcanary/pull/1313) [#1314](https://github.com/square/leakcanary/pull/1314) [#1340](https://github.com/square/leakcanary/pull/1340) [#1337](https://github.com/square/leakcanary/pull/1337) Many API changes
1299* [#1296](https://github.com/square/leakcanary/pull/1296) [#1293](https://github.com/square/leakcanary/pull/1293) [#1306](https://github.com/square/leakcanary/pull/1306) [#1336](https://github.com/square/leakcanary/pull/1336) Fixed several crashes.
1300
1301Many thanks to
1302[@forrestbice](https://github.com/forrestbice),
1303[@Foso](https://github.com/Foso),
1304[@Goddchen](https://github.com/Goddchen),
1305[@marcosholgado](https://github.com/marcosholgado),
1306[@orionlee](https://github.com/orionlee),
1307[@pyricau](https://github.com/pyricau),
1308[@satoshun](https://github.com/satoshun),
1309[@ZacSweers](https://github.com/ZacSweers)
1310for the contributions!
1311
1312For more details, see the [2.0-alpha-2 Milestone](https://github.com/square/leakcanary/milestone/7) and the [full diff](https://github.com/square/leakcanary/compare/v2.0-alpha-1...v2.0-alpha-2).
1313
1314## Version 2.0 Alpha 1 (2019-04-23)
1315
1316![logo](images/logo-2.0-200px.png)
1317
1318* New [logo](https://github.com/square/leakcanary/wiki/FAQ#who-made-the-logo), thanks [@flickator](https://github.com/flickator)!
1319* Entirely rewritten to **100% Kotlin**
1320* Multiple leaks detected in one analysis
1321    * The heap is dumped when the app goes in the background, or when a minimum of 5 leaks is reached in the foreground.
1322* Leak grouping
1323    * Leaks that share similar causes are grouped in the UI.
1324    * New screens to see the list of groups and each group.
1325    * Improved leaktrace strings to highlight leak causes.
1326    * Leaks can be shared to Stack Overflow
1327* New library: **LeakSentry**.
1328    * Detects when objects are leaking and triggers LeakCanary
1329    * Can be used independently in production, for instance to report the number of leaking instances on an OutOfMemoryError crash.
1330* New heap parser
1331    * Uses **90% less memory and 6 times** faster than the prior heap parser.
1332    * Runs in the same process as the app on a low priority thread.
1333    * No more dependency on Perflib and TroveJ. New dependency on Okio.
1334    * The old parser is still available as `leakcanary-android-perflib` but will be removed after alpha.
1335* Labelers can add any string content to leak elements
1336* 0 code setup, just add the one debug dependency.
1337* Simpler configuration options
1338* Updated from support library to Android X
1339
1340Many thanks to
1341[@BraisGabin](https://github.com/BraisGabin),
1342[@colinmarsch](https://github.com/colinmarsch),
1343[@jrodbx](https://github.com/jrodbx),
1344[@flickator](https://github.com/flickator),
1345[@JakeWharton](https://github.com/JakeWharton),
1346[@pyricau](https://github.com/pyricau),
1347[@WhatsEmo](https://github.com/WhatsEmo)
1348for the contributions!
1349
1350For more details, see the [2.0-alpha-1 Milestone](https://github.com/square/leakcanary/milestone/6) and the [full diff](https://github.com/square/leakcanary/compare/v1.6.3...v2.0-alpha-1).
1351
1352## Version 1.6.3 (2019-01-10)
1353
1354* [#1163](https://github.com/square/leakcanary/issues/1163) Fixed leaks being incorrectly classified as "no leak" due to missed GC Roots.
1355* [#1153](https://github.com/square/leakcanary/issues/1153) `LeakCanary.isInAnalyzerProcess` now correctly returns true in the analyzer process prior to any first leak (could be triggered by starting the leak result activity).
1356* [#1158](https://github.com/square/leakcanary/issues/1158) Stopped enabling DisplayLeakActivity when not using DisplayLeakService.
1357* [#1135](https://github.com/square/leakcanary/issues/1135) Fixed IndexOutOfBoundsException for leak traces of size 1.
1358* [#1163](https://github.com/square/leakcanary/issues/1163) Keep "no leak" heap dumps.
1359
1360Many thanks to
1361[@KMaragh](https://github.com/KMaragh),
1362[@pyricau](https://github.com/pyricau),
1363[@SebRut](https://github.com/SebRut)
1364for the code contributions!
1365
1366For more details, see the [1.6.3 Milestone](https://github.com/square/leakcanary/milestone/5) and the [full diff](https://github.com/square/leakcanary/compare/v1.6.2...v1.6.3).
1367
1368
1369## Version 1.6.2 (2018-10-16)
1370
1371* [#1067](https://github.com/square/leakcanary/issues/1067) Fixed TransactionTooLargeException crash (leak analysis would never complete).
1372* [#1061](https://github.com/square/leakcanary/pull/1061) Detection of Fragment view leaks after Fragment#onDestroyView().
1373* [#1076](https://github.com/square/leakcanary/pull/1076) Added the FOREGROUND_SERVICE permission for Android P.
1374* [#1062](https://github.com/square/leakcanary/issues/1062) The LeakCanary toast now always shows correctly. It doesn't show if there is no activity in foreground.
1375* [#1115](https://github.com/square/leakcanary/issues/1115) Reenabled the DisplayLeakActivity icon on fresh installs.
1376* [#1100](https://github.com/square/leakcanary/pull/1100) Added nullability annotations to improve Kotlin support.
1377* Updates to excluded leaks ([commits](https://github.com/square/leakcanary/commits/v1.6.2/leakcanary-android/src/main/java/com/squareup/leakcanary/AndroidExcludedRefs.java)).
1378* Updates to reachability inspectors ([commits](https://github.com/square/leakcanary/commits/v1.6.2/leakcanary-android/src/main/java/com/squareup/leakcanary/AndroidReachabilityInspectors.java)).
1379
1380Many thanks to
1381[@fractalwrench](https://github.com/fractalwrench),
1382[@ZacSweers](https://github.com/ZacSweers),
1383[@Goddchen](https://github.com/Goddchen),
1384[@igokoro](https://github.com/igokoro),
1385[@IlyaGulya](https://github.com/IlyaGulya),
1386[@JakeWharton](https://github.com/JakeWharton),
1387[@javmarina](https://github.com/javmarina),
1388[@jokermonn](https://github.com/jokermonn),
1389[@jrodbx](https://github.com/jrodbx),
1390[@Parseus](https://github.com/Parseus),
1391[@pyricau](https://github.com/pyricau),
1392[@scottkennedy](https://github.com/scottkennedy)
1393for the code contributions!
1394
1395### Public API changes
1396
1397* Subclasses of `AbstractAnalysisResultService` should now override `onHeapAnalyzed(@NonNull AnalyzedHeap analyzedHeap)` instead of `onHeapAnalyzed(@NonNull HeapDump heapDump, @NonNull AnalysisResult result)`
1398
1399For more details, see the [1.6.2 Milestone](https://github.com/square/leakcanary/milestone/4) and the [full diff](https://github.com/square/leakcanary/compare/v1.6.1...v1.6.2).
1400
1401## Version 1.6.1 (2018-06-21)
1402
1403* [#727](https://github.com/square/leakcanary/issues/727) Improved leak analysis: LeakCanary now identifies and highlights the potential causes of the leak.
1404* [#1011](https://github.com/square/leakcanary/issues/1011) We noticed that computing the retained heap size could take a long time, so it's now optional and off by default.
1405* [#633](https://github.com/square/leakcanary/pull/633) Support for detecting leaks in instrumentation tests ([see the wiki](https://github.com/square/leakcanary/wiki/Customizing-LeakCanary#running-leakcanary-in-instrumentation-tests)).
1406* [#985](https://github.com/square/leakcanary/pull/985) Ability to convert leak traces into stack traces for easy remote reporting ([see the wiki](uploading.md)).
1407* [#983](https://github.com/square/leakcanary/issues/983) Support for watching destroyed Fragments.
1408* [#846](https://github.com/square/leakcanary/issues/846) LeakCanary now uses foreground services and displays a notification when the analysis is in progress. This also fixes crashes when analyzing in background on O+.
1409* The LeakCanary icon (to start to DisplayLeakActivity) is now hidden by default, and only enabled after the first leak is found.
1410* [#775](https://github.com/square/leakcanary/issues/775) Fixed crash when sharing heap dumps on O+ and added a dependency to the support-core-utils library.
1411* [#930](https://github.com/square/leakcanary/pull/930) DisplayLeakActivity has a responsive icon.
1412* [#685](https://github.com/square/leakcanary/issues/685) Stopped doing IO on main thread in DisplayLeakActivity (fixes StrictMode errors).
1413* [#999](https://github.com/square/leakcanary/pull/999) Updated HAHA to 2.0.4, which uses Trove4j as an external dependency (from jcenter) instead of rebundling it. This is to clarify licences (Apache v2 vs LGPL 2.1).
1414* Several bug and crash fixes.
1415
1416Many thanks to [@AdityaAnand1](https://github.com/AdityaAnand1), [@alhah](https://github.com/alhah), [@christxph](https://github.com/christxph), [@csoon03](https://github.com/csoon03), [@daqi](https://github.com/daqi), [@JakeWharton](https://github.com/JakeWharton), [@jankovd](https://github.com/jankovd), [@jrodbx](https://github.com/jrodbx), [@kurtisnelson](https://github.com/kurtisnelson), [@NightlyNexus](https://github.com/NightlyNexus), [@pyricau](https://github.com/pyricau), [@SalvatoreT](https://github.com/SalvatoreT), [@shmuelr](https://github.com/shmuelr), [@tokou](https://github.com/tokou), [@xueqiushi](https://github.com/xueqiushi)
1417 for the code contributions!
1418
1419Note: we made a 1.6 release but quickly followed up with 1.6.1 due to [#1058](https://github.com/square/leakcanary/issues/1058).
1420
1421### Public API changes
1422
1423* The installed ref watcher singleton is now available via `LeakCanary.installedRefWatcher()`
1424* `AnalysisResult.leakTraceAsFakeException()` returns an exception that can be used to report and group leak traces to a tool like Bugsnag or Crashlytics.
1425* New `InstrumentationLeakDetector` and `FailTestOnLeakRunListener` APIs for detecting leaks in instrumentation tests.
1426* New `Reachability.Inspector` and `RefWatcherBuilder.stethoscopeClasses()` API to establish reachability and help identify leak causes.
1427* Watching activities can be disabled with `AndroidRefWatcherBuilder.watchActivities(false)`, watching fragments can be disabled with `AndroidRefWatcherBuilder.watchFragments(false)`
1428* `LeakCanary.setDisplayLeakActivityDirectoryProvider()` is deprecated and replaced with `LeakCanary.setLeakDirectoryProvider()`
1429* New `RefWatcherBuilder.computeRetainedHeapSize()` API to enable the computing of the retained heap size (off by default).
1430
1431For more details, see the [1.6.1 Milestone](https://github.com/square/leakcanary/milestone/3) and the [full diff](https://github.com/square/leakcanary/compare/v1.5.4...v1.6.1).
1432
1433## Version 1.5.4 *(2017-09-22)*
1434
1435* Restore Java 7 compatibility in leakcanary-watcher
1436
1437## Version 1.5.3 *(2017-09-17)*
1438
1439* Fix broken 1.5.2 [build](https://github.com/square/leakcanary/issues/815)
1440* Convert leakcanary-watcher from Android library to Java library
1441* Disable finish animations in RequestStoragePermissionActivity
1442* Corrected README sample for Robolectric tests
1443
1444For more details, see the [full diff](https://github.com/square/leakcanary/compare/v1.5.2...v1.5.3).
1445
1446## Version 1.5.2 *(2017-08-09)*
1447
1448* New excluded leaks
1449* Move Leakcanary UI into leak analyzer process
1450* Ignore computing retained sizes for bitmaps on O+
1451* Add notification channel for persistent messages on O+
1452* Exclude permission activity from recents menu
1453* Updated README and sample for handling Robolectric tests
1454
1455For more details, see the [full diff](https://github.com/square/leakcanary/compare/v1.5.1...v1.5.2).
1456
1457## Version 1.5.1 *(2017-04-25)*
1458
1459* New excluded leaks
1460* Fix java.util.MissingFormatArgumentException in DisplayLeakService
1461* Separate task affinities for different apps
1462* Bump minSdk to 14
1463* Fix HahaHelper for O Preview
1464
1465For more details, see the [full diff](https://github.com/square/leakcanary/compare/v1.5...v1.5.1).
1466
1467## Version 1.5 *(2016-09-28)*
1468
1469* New excluded leaks
1470* Added `LeakCanary.isInAnalyzerProcess()` to the no-op jar
1471* Fixed several file access issues:
1472    * No more cleanup on startup, we rotate the heap dump files on every new heap dump.
1473    * LeakCanary now falls back to the app directory until it can write to the external storage.
1474* Leak notifications now each use a distinct notification instead of erasing each other.
1475* If LeakCanary can't perform a heap dump for any reason (e.g. analysis in progress, debugger attached), it retries later with an exponential backoff.
1476* Added confirmation dialog when user deletes all leaks.
1477* Replace the two LeakCanary configuration methods with a builder that provides more flexibility, see `LeakCanary.refWatcher()`.
1478
1479For more details, see the [full diff](https://github.com/square/leakcanary/compare/v1.4...v1.5).
1480
1481### Public API changes
1482
1483* New `HeapAnalyzer.findTrackedReferences()` method for headless analysis when you have no context on what leaked.
1484* Added `LeakCanary.isInAnalyzerProcess()` to the no-op jar
1485* Added `LeakCanary.refWatcher()` which returns an `AndroidRefWatcherBuilder` that extends `RefWatcherBuilder` and lets you fully customize the `RefWatcher` instance.
1486* Removed `LeakCanary.install(Application, Class)` and `LeakCanary.androidWatcher(Context, HeapDump.Listener, ExcludedRefs)`.
1487* Removed `R.integer.leak_canary_max_stored_leaks` and `R.integer.leak_canary_watch_delay_millis`, those can now be set via `LeakCanary.refWatcher()`.
1488* Updated the `LeakDirectoryProvider` API to centralize all file related responsibilities.
1489* `RefWatcher` is now constructed with a `WatchExecutor` which executes a `Retryable`, instead of an `Executor` that executes a `Runnable`.
1490* `HeapDumper.NO_DUMP` was renamed `HeapDumper.RETRY_LATER`
1491
1492## Version 1.4 *(2016-09-11)*
1493
1494* Fix false negative where GC root is of type android.os.Binder [#482](https://github.com/square/leakcanary/issues/482)
1495* Update HAHA to 2.0.3; clear compiler warnings [#563](https://github.com/square/leakcanary/issues/563)
1496* Correct some mistakes in German translation [#516](https://github.com/square/leakcanary/pull/516)
1497* Don't loop when storage permission denied [#422](https://github.com/square/leakcanary/issues/422)
1498* Remove old references to "__" prefixed resources [#477](https://github.com/square/leakcanary/pull/477)
1499* Fix permission crash for DisplayLeakActivity on M [#382](https://github.com/square/leakcanary/issues/382)
1500* Fix NPE when thread name not found in heap dump [#417](https://github.com/square/leakcanary/issues/417)
1501* Add version info to stacktrace [#473](https://github.com/square/leakcanary/issues/473)
1502
1503## Version 1.4-beta2 *(2016-03-23)*
1504
1505* Add reason for ignoring to analysis result [#365](https://github.com/square/leakcanary/issues/365).
1506* Lower memory usage when parsing heap dumps on M [#223](https://github.com/square/leakcanary/issues/223).
1507* Fix NPE in LeakCanaryInternals.isInServiceProcess() [#449](https://github.com/square/leakcanary/issues/449).
1508* New ignored Android SDK leaks [#297](https://github.com/square/leakcanary/issues/297),[#322](https://github.com/square/leakcanary/issues/322).
1509* Use leakcanary-android-no-op in test builds [#143](https://github.com/square/leakcanary/issues/143).
1510* Fixes to allow LeakCanary to work with ProGuard [#398](https://github.com/square/leakcanary/pull/398).
1511* Optimize png assets [#406](https://github.com/square/leakcanary/pull/406).
1512* Fix delete button not working on error views [#408](https://github.com/square/leakcanary/pull/408).
1513* Add German translation [#437](https://github.com/square/leakcanary/pull/437).
1514
1515## Version 1.4-beta1 *(2016-01-08)*
1516
1517* Switched to [HAHA 2.0.2](https://github.com/square/haha/blob/master/CHANGELOG.md#version-202-2015-07-20) with uses Perflib instead of MAT under the hood [#219](https://github.com/square/leakcanary/pull/219). This fixes crashes and improves speed a lot.
1518* We can now parse Android M heap dumps [#267](https://github.com/square/leakcanary/issues/267), although there are still memory issues (see [#223](https://github.com/square/leakcanary/issues/223)).
1519* Excluded leaks are now reported as well and available in the display leak activity.
1520* Added ProGuard configuration for [#132](https://github.com/square/leakcanary/issues/132).
1521* Many new ignored Android SDK leaks.
1522* Added excluded leaks to text report [#119](https://github.com/square/leakcanary/issues/119).
1523* Added LeakCanary SHA to text report [#120](https://github.com/square/leakcanary/issues/120).
1524* Added CanaryLog API to replace the logger: [#201](https://github.com/square/leakcanary/issues/201).
1525* Renamed all resources to begin with `leak_canary_` instead of `__leak_canary`[#161](https://github.com/square/leakcanary/pull/161)
1526* No crash when heap dump fails [#226](https://github.com/square/leakcanary/issues/226).
1527* Add retained size to leak reports [#162](https://github.com/square/leakcanary/issues/162).
1528
1529### Public API changes
1530
1531* AnalysisResult.failure is now a `Throwable` instead of an `Exception`. Main goal is to catch and correctly report OOMs while parsing.
1532* Added ARRAY_ENTRY to LeakTraceElement.Type for references through array entries.
1533* Renamed `ExcludedRefs` fields.
1534* Each `ExcludedRef` entry can now be ignored entirely or "kept only if no other path".
1535* Added support for ignoring all fields (static and non static) for a given class.
1536
1537## Version 1.3.1 *(2015-05-16)*
1538
1539* Heap dumps and analysis results are now saved on the sd card: [#21](https://github.com/square/leakcanary/issues/21).
1540* `ExcludedRef` and `AndroidExcludedRefs` are customizable: [#12](https://github.com/square/leakcanary/issues/12) [#73](https://github.com/square/leakcanary/issues/73).
1541* 7 new ignored Android SDK leaks: [#1](https://github.com/square/leakcanary/issues/1) [#4](https://github.com/square/leakcanary/issues/4) [#32](https://github.com/square/leakcanary/issues/32) [#89](https://github.com/square/leakcanary/pull/89) [#82](https://github.com/square/leakcanary/pull/82) [#97](https://github.com/square/leakcanary/pull/97).
1542* Fixed 3 crashes in LeakCanary: [#37](https://github.com/square/leakcanary/issues/37) [#46](https://github.com/square/leakcanary/issues/46) [#66](https://github.com/square/leakcanary/issues/66).
1543* Fixed StrictMode thread policy violations: [#15](https://github.com/square/leakcanary/issues/15).
1544* Updated `minSdkVersion` from `9` to `8`: [#57](https://github.com/square/leakcanary/issues/57).
1545* Added LeakCanary version name to `LeakCanary.leakInfo()`: [#49](https://github.com/square/leakcanary/issues/49).
1546* `leakcanary-android-no-op` is lighter, it does not depend on `leakcanary-watcher` anymore, only 2 classes now: [#74](https://github.com/square/leakcanary/issues/74).
1547* Adding field state details to the text leak trace.
1548* A Toast is displayed while the heap dump is in progress to warn that the UI will freeze: [#20](https://github.com/square/leakcanary/issues/49). You can customize the toast by providing your own layout named `__leak_canary_heap_dump_toast.xml` (e.g. you could make it an empty layout).
1549* If the analysis fails, the result and heap dump are kept so that it can be reported to LeakCanary: [#102](https://github.com/square/leakcanary/issues/102).
1550* Update to HAHA 1.3 to fix a 2 crashes [#3](https://github.com/square/leakcanary/issues/3) [46](https://github.com/square/leakcanary/issues/46)
1551
1552### Public API changes
1553
1554* When upgrading from 1.3 to 1.3.1, previously saved heap dumps will not be readable any more, but they won't be removed from the app directory. You should probably uninstall your app.
1555* Added `android.permission.WRITE_EXTERNAL_STORAGE` to `leakcanary-android` artifact.
1556* `LeakCanary.androidWatcher()` parameter types have changed (+ExcludedRefs).
1557* `LeakCanary.leakInfo()` parameter types have changed (+boolean)
1558* `ExcludedRef` is now serializable and immutable, instances can be created using `ExcludedRef.Builder`.
1559* `ExcludedRef` is available in `HeapDump`
1560* `AndroidExcludedRefs` is an enum, you can now pick the leaks you want to ignore in `AndroidExcludedRefs` by creating an `EnumSet` and calling `AndroidExcludedRefs.createBuilder()`.
1561* `AndroidExcludedRefs.createAppDefaults()` & `AndroidExcludedRefs.createAndroidDefaults()` return a `ExcludedRef.Builder`.
1562* `ExcludedRef` moved from `leakcanary-analyzer` to `leakcanary-watcher`
1563
1564## Version 1.3 *(2015-05-08)*
1565
1566Initial release.
1567
1568### Dependencies
1569