square / leakcanary

A memory leak detection library for Android.
https://square.github.io/leakcanary
Apache License 2.0
29.41k stars 3.97k forks source link

Memory Leak at Toast #2497

Closed wflin2020 closed 1 year ago

wflin2020 commented 1 year ago

I add LeakCanary(version:2.10) and I has this memory leak in my application. Here is my toast utils

public class ToastUtils {

    private static Toast toast = null;

    public static void showShortToast(final String msg) {
        if (toast != null) {
            toast.cancel();
        }
        toast = Toast.makeText(App.getContext(), msg, Toast.LENGTH_SHORT);
        if (toast != null) {
            toast.show();
        }
    }

}

When I call the showShortToast funcation, then finish the activity, I will receive a memory leak notification

 ┬───
    │ GC Root: Thread object
    │
    ├─ android.os.HandlerThread instance
    │    Leaking: NO (PathClassLoader↓ is not leaking)
    │    Thread name: 'LeakCanary-Heap-Dump'
    │    ↓ Thread.contextClassLoader
    ├─ dalvik.system.PathClassLoader instance
    │    Leaking: NO (ToastUtils↓ is not leaking and A ClassLoader is never leaking)
    │    ↓ ClassLoader.runtimeInternalObjects
    ├─ java.lang.Object[] array
    │    Leaking: NO (ToastUtils↓ is not leaking)
    │    ↓ Object[844]
    ├─ com.xxx.toast_leak.ToastUtils class
    │    Leaking: NO (a class is never leaking)
    │    ↓ static ToastUtils.toast
    │                        ~~~~~
    ├─ android.widget.Toast instance
    │    Leaking: YES (This toast is done showing (Toast.mTN.mWM != null && Toast.mTN.mView == null))
    │    Retaining 5.6 kB in 63 objects
    │    mContext instance of com.xxx.toast_leak.App
    │    ↓ Toast.mNextView
    ╰→ android.widget.LinearLayout instance
    ​     Leaking: YES (ObjectWatcher was watching this because android.widget.LinearLayout received
    ​     View#onDetachedFromWindow() callback)
    ​     Retaining 3.6 kB in 56 objects
    ​     key = a3e0b0ae-093e-4084-87d2-0ea649deb86e
    ​     watchDurationMillis = 325827
    ​     retainedDurationMillis = 320823
    ​     View not part of a window view hierarchy
    ​     View.mAttachInfo is null (view detached)
    ​     View.mWindowAttachCount = 1
    ​     mContext instance of com.xxx.toast_leak.App

    METADATA

    Build.VERSION.SDK_INT: 29
    Build.MANUFACTURER: HUAWEI
    LeakCanary version: 2.10
    App process name: com.xxx.toast_leak
    Class count: 13910
    Instance count: 107300
    Primitive array count: 81669
    Object array count: 12478
    Thread count: 17
    Heap total bytes: 15223838
    Bitmap count: 3
    Bitmap total bytes: 82627
    Large bitmap count: 0
    Large bitmap total bytes: 0
    Stats: LruCache[maxSize=3000,hits=30543,misses=61816,hitRate=33%]
    RandomAccess[bytes=3190070,reads=61816,travel=22007533818,range=18438157,size=23610670]
    Analysis duration: 21980 ms

Could you tell me the reason of the memory leak and help me solve this problem?

pyricau commented 1 year ago

When the toast is done showing, you shouldn't keep it in memory any longer, there's no use for that. Which is what the trace is telling you:

Leaking: YES (This toast is done showing (Toast.mTN.mWM != null && Toast.mTN.mView == null))
wflin2020 commented 1 year ago

Thank you very much for your reply. One thing I don't understand is that I can't reproduce this problem on the emulator, Can I think this is a problem of some mobile phone manufacturers. If not, what is the reference chain of this memory leak(This ToastUtils is want to make an application-level toast)?