一.说明
由于android内存是一个十分宝贵的资源,所以有时候不当的代码就会造成OOM,前面几天自己写了一乐多线程的小框架,可是在我调试代码的时候却一直看见LogCat满屏的GC,这就有点慌了,从来没用过内存调试分析工具,于是今天百度了一一下,使用MAT就精确地定位内存泄漏的原因,原来是线程持有Activity一直没有释放,造成了 OOM。所以自己按照网上的资料就模拟一个OOM场景,并精确定位造成OOM的原因。
二.情景再现
使用开发工具是android studio 2.2版本,下面是具体代码:
/**
* Created by lanzhu1993 on 2016/12/29.
*/
public class ActivityHelper {
private Context mContext;
public ActivityHelper(Context context) {
this.mContext=context;
}
/**
* 打印ActivityName
*/
public void printActivityName() {
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
@Override
public void run() {
while (true)
try {
Thread.sleep(1000 * 30);
Log.d(ActivityHelper.class.getSimpleName(), ((Activity) mContext).getClass().getSimpleName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
Activity页面中的代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityHelper helper = new ActivityHelper(this);
helper.printActivityName();
}
}
从代码中可以知道,我们开启100个子线程打印Activity的名字。子线程持有Activity的对象。
下面附打印日志
然后我们打开android studio 的Android Device Monitor,按照下图操作导出hprof文件。
1.选中你的android项目的包名;
2.更新堆内存信息;
3.下载堆HPROF文件。
得到堆HPROF文件,此时就要在android SDK目录下platform-tools文件夹下打开cmd命令窗口
执行命令;
hprof-conv C:\Users\lanzhu1993\Desktop\text\com.businlinq.gctest.hprof C:\Users\lanzhu1993\Desktop\text\com.businlinq.gctest.out.hprof
C:\Users\lanzhu1993\Desktop\text\com.businlinq.gctest.hprof 下载的hprof文件路径
C:\Users\lanzhu1993\Desktop\text\com.businlinq.gctest.out.hprof 输出hprof文件路径
三.重头戏
前面的准备工作做好了,现在就要使用MAT工具进行内存分析了
MAT下载地址: http://www.eclipse.org/mat/downloads.php 根据自己的电脑选择下载版本
MAT安装好以后,打开MAT “FILE——>open head dump”打开命令执行输出的hprof文件,然后选择界面的Action 栏目下的Dominator Tree 观察,
然后按照你GC的地方的关键字进行收索就好,我这里是ActivityHelper;收索结果如下图所示。
可以知道我在子线程中持有Activity的引用,容易造成OOM,所以应保持Thread和Activity的生命周期一致来避免OOM。
四.总结
这篇博客写的比较浅,也是才接触内存管理分析,还有很多东西需要去学习,不管怎样,加油,少年!时间会让我懂得更多的。
逆风的方向,更适合飞翔!