Hold a decor view through its window, and the window through its screen The decor view rule was `Activity.mDecor` / `Dialog.mDecor`, and that field is null on a live activity more often than not. `handleResumeActivity` is the only place that writes it, under `r.window == null`, so it is set once per `ActivityClientRecord` rather than once per `Activity` — a screen recreated on a configuration change is resumed, visible, and has a null `mDecor` for the rest of its life. `PhoneWindow.mDecor` has no such gap: every decor view in the seven real dumps here is pointed at by exactly one. Moving the decor view under its window puts a window's 3 MB where the window lands, so the window needs a rule too — 6 of the 16 windows in those dumps were drawn at the top of the tree, held by a `ViewRootImpl` or a `WindowManagerImpl` as well as by their activity. With the second rule every decor view is under its window and every window of a screen that is up is under that screen. That second rule is the one whose owning reference outlives the construct it is about: `Activity.mWindow` is set in `attach` and never cleared and `Dialog.mWindow` is final, so a destroyed activity and a dismissed dialog go on pointing at a window they have nothing left to do with. Owning it anyway took the window of a leaked screen away from whatever else held it, and turned two leaks into one on the list. So it owns through `mWindow` and asks whether the screen is up of another reference, one the framework does drop — the self-clearing kind every other rule owns by, borrowed from beside the one this rule owns through. A dialog is dropped from its own `mDecor`, which `show` sets and `dismiss` nulls; an activity is dropped from `ActivityThread.mActivities`, which `handleDestroyActivity` removes the record from and which the activity rule already owns activities by. No rule reads the state of an object. Bytes are conserved on all eight dumps in the repo, no object joins or leaves the tree, and 0 to 16 objects of 34 K to 340 K move. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A memory leak detection library for Android.
🙏 If you like LeakCanary you can show support by starring ⭐ this repository.
Copyright 2015 Square, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.