如何使用泄漏金丝雀

2022-09-01 03:16:46

我目前在我的应用程序中遇到 OutOfMemoryError。我尝试过使用MAT进行调试,但是在一些活动中仍然很难找到泄漏。然后我找到了LeakCanary,它似乎更简单,更容易使用,但是即使在Google上,我也找不到任何使用Leak Canary的初学者分步指南。我已经通过build.gradle中的依赖项安装了LeakCanary,这是我到目前为止得到的:

示例应用.java

public class ExampleApplication extends Application {

    public static RefWatcher getRefWatcher(Context context) {
        ExampleApplication application = (ExampleApplication) context.getApplicationContext();
        return application.refWatcher;
    }

    private RefWatcher refWatcher;

    @Override
    public void onCreate() {
        super.onCreate();
        refWatcher = LeakCanary.install(this);
    }

    final class KeyedWeakReference extends WeakReference<Object> {
        public final String key;
        public final String name;

        KeyedWeakReference(Object referent, String key, String name,
                       ReferenceQueue<Object> referenceQueue) {
            super(checkNotNull(referent, "referent"), checkNotNull(referenceQueue, "referenceQueue"));
            this.key = checkNotNull(key, "key");
            this.name = checkNotNull(name, "name");
        }
    }

    public void watch(Object watchedReference, String referenceName) {
        checkNotNull(watchedReference, "watchReference");
        checkNotNull(referenceName, "referenceName");
        if(debuggerControl.isDebuggerAttached()) {
            return;
        }
        final long watchStartNanoTime = System.nanoTime();
        String key = UUID.randomUUID().toString();
        retainedKeys.add(key);
        final KeyedWeakReference reference =
            new KeyedWeakReference(watchedReference, key, referenceName, queue);
        watchExecutor.execute()

    }
}

假设我有一个活动,我希望LeakCanary观看一个对象

样品活性.java

public class SampleActivity extends Activity implements View.OnClickListener {
    ImageView level001, level002;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.choose_level);

        level001 = (ImageView) findViewById(R.id.level001);
        level002 = (ImageView) findViewById(R.id.level002);

        // Do all kinds of functions
        // How do I use LeakCanary to watch these objects?

    }
}

现在,我如何使用 LeakCanary 查看哪个对象导致内存泄漏?


答案 1

泄漏金丝雀的好处是它的工作原理自动化程度。默认情况下,它已经“监视”未正确 GCed 的活动。因此,开箱即用,如果有任何活动泄漏,您应该收到通知。

在我的项目中,我添加了一个额外的方法,如下所示:Application

public class ExampleApplication extends Application {
    public static ExampleApplication instance;
    private RefWatcher refWatcher;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        refWatcher = LeakCanary.install(this);
    }

    public void mustDie(Object object) {
        if (refWatcher != null) {
            refWatcher.watch(object);
        }
    }
}

因此,垃圾收集,内存泄漏和金丝雀的重要内容是知道何时应该收集内容并要求监视该项目。

例如,我们使用带有以下代码的“基本片段”:

@Override
public void onDestroy() {
    super.onDestroy();
    ExampleApplication.instance.mustDie(this);
}

这种方式是尝试检查是否有任何片段泄漏内存。LeakCanary

因此,为了进一步在您的应用程序上实现,您可以/应该在您知道应该进行垃圾回收的任务或实例上,但您认为它可能不是,并且您不确定在哪里,您也可以调用它:ExampleApplication.instance.mustDie(object);

然后,您必须运行应用程序并旋转设备并强制发生泄漏,以便泄漏金丝雀可以抓取/分析堆栈跟踪,并为您提供有关如何修复它的宝贵信息。

我希望它有帮助。


答案 2

发布此答案是因为不再需要所有其他答案,并且有更好的方法可以使用Leak Canary 2查找应用程序上的泄漏。

只需将以下依赖项添加到您的等级中即可。无需更多代码。

debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'

有关最新版本的漏金枪,请访问 https://square.github.io/leakcanary/changelog/


推荐