java - 如何使用泄漏金丝雀

标签 java android memory-leaks leakcanary

我目前在我的应用程序中遇到 OutOfMemoryError。我曾尝试使用 MAT 进行调试,但在一些 Activity 中仍然很难找到泄漏。然后我找到了 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()

    }
}

假设我有一个 Activity,我希望 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 functions
        // How do I use LeakCanary to watch these objects?

    }
}

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

最佳答案

leak canary 的好处在于它的自动化程度。 默认情况下,它已经“监视”了未正确 GC 的 Activity 。所以开箱即用,如果有任何 Activity 泄漏,您应该会收到通知。

在我的项目中,我在 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);
        }
    }
}

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

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

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

这样 LeakCanary 正在尝试检查是否有任何 fragment 在泄漏内存。

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

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

希望对你有帮助。

关于java - 如何使用泄漏金丝雀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33654503/

相关文章:

java - 计算 SpringEL 表达式时出现异常 - 由于集合而出错?

java - 如何将数据从 firestore 添加到我的 spinner

android - 如何在 PopupWindow 中为 EditText 启用选择标记?

memory-leaks - Dart Websocket内存泄漏

c++11 - 悬空指针和内存泄漏有什么区别?

java - android 更好的保存图像选项?

java - 将字符转换为大写

android - 如何添加 JSON header

android - 在Flutter中根据当前位置的经纬度获取完整的地址详细信息

node.js - 在 Node.js 中使用流时内存泄漏?