什么是内存泄露?
按照传统定义,内存泄露属于对象,正在运行的程序无法访问这个对象,但这个对象仍然占据
着内存这就叫内存泄露。这在c/c++里面的指针比较好理解。
但是在kotlin和java中情况有些不同,因为这些程序是在Java虚拟机(JVM)里面运行的,在JVM中“垃圾回收(GC)”是个重要概念,虚拟机会在GC时首先确认GC Root,GC Root是一种对象,可以从堆外访问,如本地变量,运行线程等,随后,虚拟机会辨别所有可以通过GC Root访问的对象,它们将会保留。无法通过GC Root访问的变量会被当做垃圾回收。
因此传统定义的内存泄露在JVM中并不存在。那么我们提到JVM中内存泄露的时候指的又是什么呢?
我们所指的一般是被放弃的对象,程序将永不再次使用它,但它仍然是可以访问的。
在Android 中有两种对象是绝对不可以泄露的,Fragment和Activity,因为这两者通常会占用大量的内存。
Android Studio 3.6以后Memory Profiler可以自动检测Fragment和Activity的泄露,就是抓取Heap Dump文件。
Memory Profiler是怎么发现内存泄露的呢?
Activity如果销毁了,那么我们知道程序不会再使用它了,如果它再被引用就表示泄露了。
Fragment必须与FragmentManager搭配才可用,如果发现Fragment没有和FragmentManager一起出现,这时如果它被引用就表示泄露了。但是要注意如果你正好在Fragment被创建后但被使用前的某个点Heap Dump,Memory Profiler会报一个错误的诊断结果,如果Fragment被缓存但仍未被复用也是一样。
Shallow Size:对象本身消耗内存
Native Size:本地对象的尺寸
Retained Size:保留尺寸
Depth:深度是从GC Root到这个实例的最短距离
对象距离GC Root越近,它拥有GC Root到这个实例多条路径的可能性就越高,结果是它比较不可能会被当做垃圾回收。
比如红色7,如果左边任意应用被破坏,那么红色7就会变得无法访问,被当做垃圾回收
如果想回收蓝色2,那么就必须打断左边和右边的引用
如果你看到任何深度为1的实例,那么就是很强烈的信号,代表这个实例是直接被GC Root引用的。
分析Heap Dump
写给程序员的内存泄漏治理手册
LeakCanary2.0使用及原理分析 — Kotlin重构版
读懂 Android Studio 分析工具数据 | AndroidDevSummit 中文字幕视频
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)