bingoogolapple.github.io
bingoogolapple.github.io copied to clipboard
MAT
安装
- 独立安装
- 以 Eclipse 插件的方式安装
- Help -> Eclipse MarketPlace -> 搜索「Memory Analyzer」
- Window -> Perspective -> Open Perspective -> Other -> Memory Analysis
生产 dump 文件
- jmap -dump:format=b,file=heapDump 19898
- Android
- DDMS - AndroidSDK/platform-tools/hprof-conv xxx.xxx.xxx.hprof xxx.xxx.xxx.hprof
- Android Studio - Export to standard.hprof
概念
- 内存泄漏:对象无用了,但仍然可达(未释放),垃圾回收器无法回收
- Shallow Heap:就是对象本身占用内存的大小,不包含对其他对象的引用
- 常规对象(非数组)的 Shallow Heap 由其成员变量的数量和类型决定
- 数组的 Shallow Heap 由数组元素的类型(对象类型、基本类型)和数组长度决定
- Retained Heap:是该对象自己的 Shallow Heap,加上从该对象能直接或间接访问到对象的 Shallow Heap 之和。换句话说,Retained Heap 就是该对象被 GC 之后所能回收到内存的总和(当 A 和 B 同时引用 C 时,A 的 Retained Heap 是不准确的,需要排除被 GC Roots 直接或者间接引用的对象)
- outgoing references:表示该对象的出节点(被该对象引用的对象)
- incoming references:表示该对象的入节点(引用到该对象的对象)
- GC Roots:GC 发现通过任何引用链无法访问某个对象的时候,该对象即被回收。名词 GC Roots 正是分析这一过程的起点,例如 JVM 自己确保了对象的可到达性(那么 JVM 就是 GC Roots),所以 GC Roots 就是这样在内存中保持对象可到达性的,一旦不可到达,即被回收。通常 GC Roots 是一个在当前线程的调用栈上的对象(例如方法参数和局部变量),或者是线程自身或者是系统类加载器加载的类以及 Native Code 保留的活动对象。所以 GC Roots 是分析对象为何还存活于内存中的利器
- Java 的引用规则
- Strong Ref (强引用):通常我们编写的代码都是 Strong Ref,于此对应的是强可达性,只有去掉强可达,对象才被回收
- Soft Ref (软引用):如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。软引用可用来实现内存敏感的高速缓存,通过 java.lang.ref.SoftReference 类实现
- Weak Ref (弱引用):只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存,不必等到内存吃紧的时候。通过 java.lang.ref.WeakReference 和 java.util.WeakHashMap 类实现
- Phantom Ref (虚引用):根本不会在内存中保持任何对象,你只能使用 Phantom Ref 本身。一般用于在进入 finalize() 方法后进行特殊的清理过程,通过 java.lang.ref.PhantomReference 实现。虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中
- 年轻代拷贝算法,减少内存碎片
- 老年代标记-清除算法(CMS),实现以获取最短回收停顿时间为目标的收集器(增加 CPU 负担)
Histogram 可以列出内存中的对象,对象的个数以及大小
- Objects:类的对象的数量。
- 查看到 GC Root 的最短路径引用链(泄漏的对象一定是在 GC Root 引用链上的),排除软、弱、虚引用
- OQL
Dominator Tree 列出最大的对象以及其依赖存活的 Object
Top Consumers 通过图形列出最大的 Object
这里显示了内存中最大的对象有哪些,他们对应的类是哪些,类加载器 Classloader 是哪些。有些时候,我们在这里就可以看到代码内存泄露的位置
Leak Suspects 通过 MAT 自动分析内存泄漏的原因
- 通过 Leak Suspects 的 Problem Suspect 1 点击「Details」,上下文菜单中选择 List objects -> with outgoning references, 查看对应对象都引用了些什么对象
- 继续查看被引用对象的 gc ROOT,上下文菜单中选择 Path To GC Roots -> exclude weak references, 过滤掉弱引用,因为在这里弱引用不是引起问题的关键
内存频繁的分配与回收,分配速度大于回收速度时,最终会产生 OOM
- WebView 放到子进程里
- 数据量千级以内可以使用过 SparseXxx(key 为整数)、ArrayMap(key 为对象),性能不及 HashMap,但节约内存
- 枚举优化,改用 IntDef、StringDef
- static final 比 static 速度更快,但会增加 apk 大小
- 避免重复申请内存(同一个方法多次调用,递归函数、回调函数new对象、读流时再循环中new对象等)
- 不要在 onMeasure、onLayout、onDraw 中去刷新 UI(requestLayout、invalidate 等),开始内存消耗不大,要过很久才会有问题,比较难排查
http://blog.sina.com.cn/s/blog_46d5caa401019vj5.html http://www.lightskystreet.com/2015/09/01/mat_usage