为什么这是内存泄漏

Boo*_*per 10 android memory-leaks leakcanary

我在Android(Java)中遇到了一个名为LeakCanary的内存泄漏检测库,但无法理解他们泄漏内存的示例.任何人都可以解释他们的示例中显示的代码是如何以及为什么是内存泄漏.

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;
Run Code Online (Sandbox Code Playgroud)

然后他们观察schrodingerCat泄漏的变量,如下所示给出泄漏(我不知道如何与上面的代码相关).

* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
Run Code Online (Sandbox Code Playgroud)

任何有关泄漏的解释以及检测与其相关的帮助都将非常有帮助.另外一些适合初学者的好文章也不错.

谢谢!

Eya*_*ran 13

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

定义

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

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

猫在一个盒子里

假设我们的应用程序中有一个Cat对象,我们将其保存在Box对象中.如果我们按住该框(具有对Box对象的引用)并且Box持有Cat,则GC将无法从内存中清除Cat对象.

Docker是一个具有静态引用Box的类.这意味着除非我们将其置零或重新赋值,否则Docker将继续引用Box.防止盒子(以及内部Cat)被GC从内存中移除.

那么,我们需要猫吗?它仍然适用于应用程序?

这取决于开发人员决定我们需要多长时间. LeakCanary和其他诊断工具表明可能存在内存泄漏.他们认为可能不再需要物体(Cat),因此他们警告它是泄漏.

概括

在该示例中,它们给出了内存泄漏的常见情况.使用静态引用时,我们阻止GC清理对象.你应该读这个:

* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
Run Code Online (Sandbox Code Playgroud)

如:

  • 对象Cat 可能不再使用,但GC未从内存中删除.
  • 没有删除对象Cat的原因是Box正在引用它.
  • 没有删除对象框的原因是因为Docker有一个静态引用它.
  • Docker的静态引用是导致可能泄漏的树的ROOT.

  • 这个很好的解释应该添加到 LeakCanary 的 wiki :) (2认同)