前言
之前写了一篇《性能优化系列-内存抖动》简单实用Memory Profiler工具解决内存抖动的情况,这边文章写实用工具配合MAT解决内存泄漏。
内存泄漏介绍
- 定义:内存中存在已经没有用的对象
- 表现:内存泄漏引起,内存泄漏,可用内存逐渐减少,系统为了增加可用内存就会一直GC,导致内存抖动。
- 危害: 内存不足、GC频繁、OOM
Memory Analyzer
- Download
- 转换HROF-ENV
内存泄漏用例
MemoryLeakActivity
class MemoryLeakActivity : AppCompatActivity(),ImageCallBack {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_memory_leak)
var bitmap = BitmapFactory.decodeResource(resources,R.mipmap.splash)
conent_iv.setImageBitmap(bitmap)
CallBackManager.addCallBack(this)
}
override fun handleImage(url: String) {
}
}
ImageCallBack
package com.martin.perfomance.memory
interface ImageCallBack {
fun handleImage(url:String)
}
CallBackManager
object CallBackManager {
var callBackList:MutableList<ImageCallBack> = mutableListOf()
/**
* 添加监听
*/
fun addCallBack(callback:ImageCallBack){
callBackList.add(callback)
}
/**
* 移除监听
*/
fun removeCallBack(callback: ImageCallBack){
callBackList.remove(callback)
}
}
内存泄漏解决实战
可以看见我们在频繁进入界面后,并没有释放当前的Activity。目前可以从图案中查看内存呈现梯形上升,表明我们创建的对象并没有被释放。那么我们如何进一步的分析是哪段代码导致这样的情况呢?
通过上面的两步,我获得了hprof
的内存快照,接下来我们MAT工具进行内存分析。
如果Mac上的独立版本无法打开文件可以参考《Mac Mat独立版本打开失败解决方案》
MAT查看Hprof的内存分布情况
进入/Users/martin/Library/Android/sdk/platform-tools
使用命令,将刚生成的hprof
文件进行转换。
hprof-conv /Users/martin/Workspace/memory-20200205T184519.hprof /Users/martin/Workspace/memory-leak_transed.hprof
使用mat打开查看图片
查看内存的分布情况:
从上面我们可以搜索对象在内存中的情况,这里我们搜索内存泄漏的对象MemoryLeakActivity
可以看见MemoryLeakActivity
在内存中有4个对象,这是很不合理的。
我们可以通过右键可以查看当前对象被什么地方引用。
- with outgoing references:被引用的地方
- with incoming references:哪些强引用引向了我
然后我们查看GCRoot的路径,查询所有的引用。
可以看见,这里集合对象保存了我们的Activity对象,导致无法释放。
MAT工具详解
这里简单介绍一下MAT工具一些使用的功能,方便我们以后查看。
首先,我们需要查看下以包结构显示对象在内存中的情况,如图:
Histogram
domaintor_tree
从基于实例的角度,查看对象占用的百分比
Percentage:代表对象占用的百分比,上面可以看见图片所占内存比重较大,是内存的大头。
OQL
通过SQL语句查询对象
Top Consumer
查看对象在内存中的占用排行,对内存优化比较有帮助。
Leak Sespect
工具直接分写,内存泄漏的情况。
总结
回顾下上面的操作:
- 通过
Memory Profiler
去查看内存实用情况,并且将内存文件hrof进行转换。 - 实用MAT工具分析分析hropf格式的文件。