首页 > 解决方案 > KeyguardManager 内存泄漏

问题描述

活动完成后,我正在使用此代码 DismissKeyguard LeakCanary 显示以下消息。如何防止这些泄漏。

keyguardManager = (KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE);

if(Build.VERSION.SDK_INT >= 27) {

    setShowWhenLocked(true);
    setTurnScreenOn(true);

    if (keyguardManager != null) {
        keyguardManager.requestDismissKeyguard(this, null);
    }
}

LeakCanary 显示

GC Root: Global variable in native code
    │
    ├─ android.app.KeyguardManager$1 instance
    │    Leaking: UNKNOWN
    │    Anonymous subclass of com.android.internal.policy.IKeyguardDismissCallback$Stub
    │    ↓ KeyguardManager$1.val$activity
    │                        ~~~~~~~~~~~~
    ╰→ com.example.myapplication.MainActivity instance
    ​     Leaking: YES (ObjectWatcher was watching this because com.example.myapplication.MainActivity received Activity#onDestroy() callback and Activity#mDestroyed is true)
    ​     

标签: androidleakcanary

解决方案


泄漏跟踪表明本机代码中存在一个全局变量,该变量保留了对KeyguardManager$1implements的实例的引用com.android.internal.policy.IKeyguardDismissCallback$Stub,并且KeyguardManager$1它本身保留了对活动的引用。

KeyguardManager#requestDismissKeyguard 的实现来源可以在这里找到:https ://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/KeyguardManager.java#574:

ActivityTaskManager.getService().dismissKeyguard(
        activity.getActivityToken(), new IKeyguardDismissCallback.Stub() {
    @Override
    public void onDismissError() throws RemoteException {
        if (callback != null && !activity.isDestroyed()) {
            activity.mHandler.post(callback::onDismissError);
        }
    }
    @Override
    public void onDismissSucceeded() throws RemoteException {
        if (callback != null && !activity.isDestroyed()) {
            activity.mHandler.post(callback::onDismissSucceeded);
        }
    }
    @Override
    public void onDismissCancelled() throws RemoteException {
        if (callback != null && !activity.isDestroyed()) {
            activity.mHandler.post(callback::onDismissCancelled);
        }
    }
}, message);

这是对 ActivityTaskManager 服务进程的进程间调用。设置为在 ActivityTaskManager 服务进程回调时接收结果的存根持有对活动的引用。不幸的是,本机存根在内存中的保存时间往往比预期的要长,因为它们依赖于在其他进程中运行的 GC。

这显然是 Android 框架中的一个错误。您应该向 Android 框架提交错误并提供重现该错误的示例应用程序。


推荐阅读