bingoogolapple.github.io icon indicating copy to clipboard operation
bingoogolapple.github.io copied to clipboard

MAT

Open bingoogolapple opened this issue 7 years ago • 5 comments

安装

  • 独立安装
  • 以 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 负担)

bingoogolapple avatar Jul 12 '17 09:07 bingoogolapple

Histogram 可以列出内存中的对象,对象的个数以及大小

  • Objects:类的对象的数量。
  • 查看到 GC Root 的最短路径引用链(泄漏的对象一定是在 GC Root 引用链上的),排除软、弱、虚引用 image
  • OQL image

bingoogolapple avatar Jul 12 '17 09:07 bingoogolapple

Dominator Tree 列出最大的对象以及其依赖存活的 Object

bingoogolapple avatar Jul 12 '17 09:07 bingoogolapple

Top Consumers 通过图形列出最大的 Object

这里显示了内存中最大的对象有哪些,他们对应的类是哪些,类加载器 Classloader 是哪些。有些时候,我们在这里就可以看到代码内存泄露的位置

bingoogolapple avatar Jul 12 '17 09:07 bingoogolapple

Leak Suspects 通过 MAT 自动分析内存泄漏的原因

  • 通过 Leak Suspects 的 Problem Suspect 1 点击「Details」,上下文菜单中选择 List objects -> with outgoning references, 查看对应对象都引用了些什么对象
  • 继续查看被引用对象的 gc ROOT,上下文菜单中选择 Path To GC Roots -> exclude weak references, 过滤掉弱引用,因为在这里弱引用不是引起问题的关键

bingoogolapple avatar Jul 12 '17 09:07 bingoogolapple

内存频繁的分配与回收,分配速度大于回收速度时,最终会产生 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

bingoogolapple avatar Jul 13 '17 05:07 bingoogolapple