最近工作中经常遇到Monkey场景中的OOM,终于摆脱忽悠测试有方法可以正常定位到问题了。
总结起来也很简单,就是两步
1.通过脚本定时抓取内存文件
2.通过MAT工具分析内存文件
1.通过ADB 命令抓取内存文件
// 查询包名对应的进程id
adb shell "pidof packagename"
// 通过进程id生成hprof内存快照在手机目录
adb shell am dumpheap 进程ID /data/local/tmp/内存快照名称.hprof
// 将内存文件pull至电脑
adb pull /data/loacl/tmp/内存快照名称.hprof 内存快照名称.hprof
获得文件后我们直接拖入AndroidSutdo即可进行分析
hprof通过AS查看.png2.通过MAT工具检查当前内存文件中的内存占用
但是OOM时dump出来的文件大小都非常的大,AS在查看的大型内存快照文件时会直接卡住。我们还需要借助MAT工具来帮助分析问题。
MAT Memory AnalyzerTool 是Eclipse项目里面用来分析java内存文件的一个工具
下载地址:https://www.eclipse.org/mat/downloads.php
通过adb命令导出的hprof文件可以在AndroidStudio中直接打开但不能在MAT中直接打开
需要借助sdk/platform-tools/hprof-conv.exe转换后才可以打开
\Android\Sdk\platform-tools\hprof-conv.exe practiceproject.hprof practiceproject-mat.hprof
打开后就可以看到页面内存分析的页面了
MAT初次打开页面.png
Shallow Heap 与Retained Heap
Shallow Heap浅堆:指的是对象自身所占据的内存,不包含其内部引用对象的大小。
Retained Heap深堆:只能通过该对象访问到的(直接或者间接)所有对象的浅堆之和,即当对象不再被引用时,垃圾回收器所能回收的总内存,包括对象自身所占据的内存,以及仅能够通过该对象引用到的其他对象所占据的内存。
如果A引用了C+D,B引用了C+E。那么A对象的深堆是A+D,同理B的深堆大小是B+E。
ShallowHeap与RetainedHeap.png
histogram 直方图
MAT 的直方图和jmap的-histo子命令一样,都能够展示各个类的实例数目以及这些实例的 Shallow heap 总和。但是,MAT 的直方图还能够计算 Retained heap,并支持基于实例数目或 Retained heap 的排序方式(默认为 Shallow heap)。
总的来说hitstogram适合去检查当前内存中哪些类的占用比例最高。
dominator tree 支配树
在 A支配 B,且 A 不同于 B 的情况下(即 A严格支配 B),如果从 A节点到 B 节点的所有路径中不存在支配 B 的其他节点,那么 A直接支配(immediate dominate)B。这里的支配树指的便是由节点的直接支配节点所组成的树状结构。
由于支配树有唯一使用的特点,使用支配树定位内存泄漏路径很方便。
outgoing和incoming
出引用(当前对象引用的外部对象)和入引用(引用当前对象的对象)
使用MAT定位安卓内存泄漏
这里我们简单使用一个例子
class LeakHolder private constructor() {
private var activity: Activity? = null
fun setActivity(activity: Activity?) {
this.activity = activity
}
companion object {
val instance = LeakHolder()
}
}
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_secend)
LeakHolder.instance.setActivity(this)
}
}
将SecondActivity交给单例LeakHolder强引用,引用关系LeakHolder -> SecondActivity
在MAT中搜所泄漏的SecondActivity右键选择Merge shortest path to GC Roots
再选择 excluede all xxxx
MAT就会帮助找到该对象的GC的路径分析路径即可找到内存泄漏的原因
找到内存泄露的原因.png
参考资料:
MemoryAnalyze(MAT)的使用 https://juejin.cn/post/6858981566405771277
网友评论