我在
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;
然后他们观察变量schrodingerCat的泄漏,给出如下所示的泄漏(我不知道如何与上述代码相关).
* GC ROOT static Docker.container * references Box.hiddenCat * leaks Cat instance
任何帮助解释泄漏和检测如何与它相关将是非常有帮助的.还有一些很好的文章,初学者会很好.
谢谢!
解决方法
首先,让我们明白什么是内存泄漏:
定义
内存泄漏是RAM中的数据分配(位图,对象,数组等),垃圾收集器(GC)无法释放,尽管程序不再需要它.
例
用户正在打开一个显示图像的视图.我们将位图加载到内存中.现在用户退出视图,并且图像不再需要,并且没有代码引用它.在那一刻,GC开始起作用,并将其从内存中删除.但是,如果我们仍然提到它,GC将不知道它可以删除,它将留在RAM中,占用不必要的空间 – 也就是内存泄漏.
猫在盒子里
假设我们的应用程序中有一个Cat对象,我们把它保存在一个Box对象中.如果我们按住Box(对Box对象的引用),Box保存Cat,GC将无法从内存中清除Cat对象.
Docker是一个对我们的Box有静态引用的类.这意味着,除非我们取消它,否则重新分配值,Docker将继续引用Box.防止盒子(和内猫)从GC中被从记忆体中除去.
那么,我们需要猫吗?它是否仍然适用于应用程序?
这取决于开发人员决定我们需要多长时间. LeakCanary和其他诊断工具建议可能的内存泄漏.他们认为对象(Cat)可能不再需要了,所以他们警告这是一个泄漏.
翻新
在该示例中,它们给出了内存泄漏的常见情况.当使用静态引用时,我们阻止了GC清理对象.你应该读这个:
* GC ROOT static Docker.container * references Box.hiddenCat * leaks Cat instance
如:
>对象猫可能不会被使用,但是GC没有被从内存中删除.>对象Cat未被删除的原因是Box正在引用它.>对象Box未被删除的原因是因为Docker具有静态引用.> Docker的静态引用是导致可能泄漏的树的ROOT.