如何使用泄漏金丝雀

Cha*_*ras 31 java android memory-leaks leakcanary

我知道这可能是一个愚蠢的问题,但我是开发android的新手,我目前在我的应用程序中遇到了OutOfMemoryError,我试图使用MAT调试,但是仍然很难找到漏洞活动,然后我找到了LeakCanary,这看起来更简单,更容易使用,但是我找不到任何有关使用Leak Canary的初学者一步一步指南,即使在Google上也是如此.我已经通过build.gradle中的依赖项安装了LeakCanary,这是我到目前为止所得到的:

ExampleApplication.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()

    }
}
Run Code Online (Sandbox Code Playgroud)

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

SampleActivity.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 function
        // How do I use LeakCanary to watch these objects ?

    }
}
Run Code Online (Sandbox Code Playgroud)

现在我如何使用LeakCanary来查看哪个对象导致内存泄漏.感谢您的帮助和帮助.

Bud*_*ius 20

关于泄漏金丝雀的好处是它的自动化程度.默认情况下,它已"监视"未正确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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以垃圾收集和内存泄漏和金丝雀的重要事情是知道应该收集什么东西并要求观看该项目.

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

@Override
public void onDestroy() {
    super.onDestroy();
    ExampleApplication.instance.mustDie(this);
}
Run Code Online (Sandbox Code Playgroud)

这种方式LeakCanary是试图检查是否有任何碎片泄漏内存.

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

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

我希望它有所帮助.


Pra*_*ash 9

Posting this answer because all other answers are no longer needed and there's a better way to find leaks on your app using Leak Canary 2.

Just add below dependency to your gradle. No more code needed.

debugImplementation 'com.squareup.leakcananry:leakcanary-android:2.7'
Run Code Online (Sandbox Code Playgroud)

  • 错别字:‘金丝雀’ (3认同)
  • 是的,你不需要 LeakCanry.Install(this) (2认同)

Mic*_*sky 6

我对如何使用 LeakCanary 有同样的问题。我只是想看看如何启动它的基本示例,并查看我的第一个泄漏对象路径。

如何使用 LeakCanary

以下是 LeakCanary 如何工作的基本示例:

如何使用 LeakCanary(4 分 13 秒)

我必须克服的问题之一是弄清楚我必须在常规运行模式而不是调试模式下启动应用程序。我还不得不偏离基本说明并按build.gradle如下方式设置我的应用程序级文件:

dependencies {
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
  releaseImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
}
Run Code Online (Sandbox Code Playgroud)

我认为debugImplementation这对我不起作用,因为LeakCanary 在调试时忽略了泄漏检测。尽管 LeakCanary 表示它提供了其库“无操作”版本以供发布,但由于调试对我不起作用,我将releaseImplementation上述内容从推荐com.squareup.leakcanary:leakcanary-android-no-op:1.5.4com.squareup.leakcanary:leakcanary-android:1.5.4.

正如您在视频中看到的,我必须处理的另一个问题是授予对 LeakCanary 的写访问权限。我向下滑动并看到来自 LeakCanary 的通知,说它无法获得写访问权限(更多信息)。我从来没有看到许可请求。因此,在一种情况下(视频中未显示),我通过转到“设置”应用程序,找到我的应用程序(而不是 LeakCanary 安装的名为“Leak”的应用程序)并打开写访问权限来授予我的应用程序写访问权限。在视频中,我不需要这样做,因为我通过回复通知给予了许可。然后在使用我的应用程序时,我会定期检查新通知(通过向下滑动)。我看到诸如“XYZActivity 泄露 217 KB”之类的消息。我点击了它,它把我带到了那个 Leak 应用程序。

此外,我注意到有时可能需要几分钟才能完成分析并在您的手机上显示内存泄漏通知

如何使用 LeakCanary 验证内存泄漏修复

现在我已经修复了一些内存泄漏,我使用 LeakCanary 来验证修复。但是,如果 LeakCanary 没有报告任何内容,我不一定相信那是因为我的泄漏已修复。可能只是 LeakCanary 坏了。

如何使用 LeakCanary 验证内存泄漏修复(16 分 34 秒)

使用 LeakCanary 验证内存泄漏的过程: 1. 使用 LeakCanary 确认内存泄漏存在 2. 修复内存泄漏并确认 LeakCanary 没有报告泄漏 3. 恢复您的修复并确认 LeakCanary 再次报告泄漏

由于 LeakCanary 在工作时显示的状态信息非常少,因此很难知道它是否正在执行任何操作。这让我以为我已经修复了内存泄漏,但实际上我没有。以上三个步骤是我发现使用 LeakCanary 验证内存泄漏修复的最佳方法。