Android 为什么这是内存泄漏

Android 为什么这是内存泄漏,android,memory-leaks,leakcanary,Android,Memory Leaks,Leakcanary,我在Android(Java)中遇到了一个用于内存泄漏检测的库,名为,但无法理解它们泄漏内存的示例。有谁能解释一下他们示例中显示的代码是如何以及为什么是内存泄漏的 class Cat { } class Box { Cat hiddenCat; } class Docker { static Box container; } // ... Box box = new Box(); Cat schrodingerCat = new Cat(); box.hiddenCat = schr

我在Android(Java)中遇到了一个用于内存泄漏检测的库,名为,但无法理解它们泄漏内存的示例。有谁能解释一下他们示例中显示的代码是如何以及为什么是内存泄漏的

class Cat {
}
class Box {
  Cat hiddenCat;
}
class Docker {
  static Box container;
}

// ...

Box box = new Box();
Cat schrodingerCat = new Cat();
box.hiddenCat = schrodingerCat;
Docker.container = box;
然后他们观察变量
schrodingerCat
是否存在泄漏,泄漏如下所示(我不知道如何与上述代码关联)

任何关于泄漏的解释以及检测与泄漏的关系的帮助都将非常有用。还有一些适合初学者的好文章


谢谢

它看起来像是用于“监视变量
schrodingerCat
是否泄漏”的
RefWatcher
实例:

强制执行一组GC过程,如果在这些GC过程中未收集传入的引用,则将其视为泄漏


由于静态
Docker.container.hiddenCat
保留了一个以GC为根的对象引用,该对象最初被称为
schrodingerCat
,因此当您要求
RefWatcher
检查它时,它不能被GC'ed。因此,它让您知道无法收集对象。

我建议您阅读此答案

它可能会帮助您理解上面的示例

简言之,在您的示例中,Docker类保留对长方体的引用。即使不再需要容器盒,类Docker仍然保留对它的引用,从而造成内存泄漏

class Cat {
}
class Box {
  Cat hiddenCat;
}
class Docker {
  static Box container;
}

// ...

Box box = new Box();
Cat schrodingerCat = new Cat();
box.hiddenCat = schrodingerCat;
Docker.container = box;

如果有帮助,请告诉我。

首先,让我们了解什么是内存泄漏:

定义

内存泄漏是指在RAM中分配的数据(位图、对象、数组等),垃圾收集器(GC)无法释放这些数据,尽管程序不再需要这些数据

示例

用户正在打开显示图像的视图。我们将位图加载到内存中。现在用户退出视图,图像不再需要,代码中也没有对它的引用。此时GC开始工作并将其从内存中删除但是,如果我们仍然有一个对它的引用,GC将不知道它可以被删除,并且它会留在RAM中,占用不必要的空间-也称为内存泄漏

盒子里的猫

假设我们的应用程序中有一个Cat对象,我们将它保存在一个Box对象中。如果我们持有box(有对box对象的引用)并且box持有Cat,那么GC将无法从内存中清除Cat对象

Docker是一个静态引用到我们的Box的类。这意味着,除非我们将其置零或重新分配值,否则Docker将继续引用该框。防止GC从内存中删除框(和内部Cat)

那么,我们需要这只猫吗?它仍然与应用程序相关吗?

这取决于开发人员来决定我们需要Cat的使用时间LeakCanary和其他诊断工具提示可能存在内存泄漏。他们认为这个物体(猫)可能不再需要了,所以他们提醒说这是个漏洞

重述

在本例中,它们给出了内存泄漏的常见场景。当使用静态引用时,我们阻止GC清理对象。您应该阅读以下内容:

* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
作为:

  • 对象Cat可能不再使用,但GC未将其从内存中删除
  • 未删除对象Cat的原因是因为框中有对它的引用
  • 未删除对象框的原因是Docker对其有静态引用
  • Docker的静态引用是导致可能泄漏的树的根

嗯?你能不能帮我把它再哑一点:)
Docker.container.hiddenCat
是对创建为
schrodingerCat
的对象的静态引用。因此,在为该对象激活
RefWatcher
时,不能对该对象进行垃圾收集。这个很好的解释应该添加到LeakCanary的wiki中:)
* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance