leakcanary
leakcanary copied to clipboard
TextClock memory leak
https://developer.android.com/reference/android/widget/TextClock
LeakTrace information
5446 bytes retained by leaking objects
Signature: 24ae8ab7f39ddd58d1df561358903f7b13726
┬───
│ GC Root: Global variable in native code
│
├─ android.database.ContentObserver$Transport instance
│ Leaking: UNKNOWN
│ Retaining 60 B in 3 objects
│ ↓ ContentObserver$Transport.mContentObserver
│ ~~~~~~~~~~~~~~~~
├─ android.widget.TextClock$FormatChangeObserver instance
│ Leaking: UNKNOWN
│ Retaining 32 B in 2 objects
│ ↓ TextClock$FormatChangeObserver.this$0
│ ~~~~~~
├─ android.widget.TextClock instance
│ Leaking: UNKNOWN
│ Retaining 1.9 kB in 23 objects
│ View not part of a window view hierarchy
│ View.mAttachInfo is null (view detached)
│ View.mID = R.id.time
│ View.mWindowAttachCount = 6
│ mContext instance of dagger.hilt.android.internal.managers.ViewComponentManager$FragmentContextWrapper, wrapping
│ activity omitted.ui.MainActivity with mDestroyed = false
│ ↓ View.mParent
│ ~~~~~~~
├─ android.widget.LinearLayout instance
│ Leaking: UNKNOWN
│ Retaining 6.6 kB in 158 objects
│ View not part of a window view hierarchy
│ View.mAttachInfo is null (view detached)
│ View.mWindowAttachCount = 6
│ mContext instance of dagger.hilt.android.internal.managers.ViewComponentManager$FragmentContextWrapper, wrapping
│ activity omitted.ui.MainActivity with mDestroyed = false
│ ↓ View.mParent
│ ~~~~~~~
╰→ android.widget.FrameLayout instance
Leaking: YES (ObjectWatcher was watching this because omitted.ui.ads.AdFragmentClock received
Fragment#onDestroyView() callback (references to its views should be cleared to prevent leaks))
Retaining 5.4 kB in 142 objects
key = f66af549-a226-4bac-af84-61059cefc47b
watchDurationMillis = 13975
retainedDurationMillis = 8969
View not part of a window view hierarchy
View.mAttachInfo is null (view detached)
View.mWindowAttachCount = 6
mContext instance of dagger.hilt.android.internal.managers.ViewComponentManager$FragmentContextWrapper, wrapping
activity omitted.ui.MainActivity with mDestroyed = false
Metadata
METADATA
Please include this in bug reports and Stack Overflow questions.
Build.VERSION.SDK_INT: 25
Build.MANUFACTURER: rockchip
LeakCanary version: 2.7
App process name: omitteed
Stats: LruCache[maxSize=3000,hits=3255,misses=61980,hitRate=4%]
RandomAccess[bytes=2978775,reads=61980,travel=28206469105,range=13379141,size=20842769]
Heap dump reason: 6 retained objects, app is visible
Analysis duration: 14796 ms
Heap dump file path: /storage/emulated/0/Download/leakcanary-omitted/2021-07-12_20-20-48_751.hprof
Heap dump timestamp: 1626146466029
Heap dump duration: 2089 ms
====================================
Sounds like a bug in either the Android SDK or a manufacturer impl, you should file an issue with a repro case, which means you need to figure out how to repro first.
Sources for TextClock are here: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/widget/TextClock.java
Also @romainguy wrote TextClock, I'm sure he'll love being pinged 🤪
The trace indicates that ContentObserver$Transport.mContentObserver
isn't null, and it is set to null when ContentObserver$Transport#releaseContentObserver()
is called, so that wasn't called, which means ContentResolver.unregisterContentObserver()
wasn't called which means TextClock.unregisterObserver()
wasn't called.
However we can see it being called in TextClock.onDetachFromWindow()
:
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mRegistered) {
unregisterReceiver();
unregisterObserver();
mRegistered = false;
}
}
The only way I can see this happening is if TextClock.setShowCurrentUserTime(boolean showCurrentUserTime)
is called, as it's the only place adding non symmetric called, and not checking / updating the mRegistered state. Looks like it's only used in KeyguardClockSwitch and SplitClockView.
To investigate further we'd need a heap dump.
No heap dump, no repro case and no issue filed to Google. Closing.
I have the same issue! How can I pass a heapdump to you?
You can upload directly to google issues, or you can uploading to google drive then share the link here and make sure it's shared with my email (py.ricau gmail.com)