如何用MAT分析Android程序的内存泄露
本文结合《Android开发艺术探索》书籍中的内存分析例子来讲解如何利用MAT工具来查找内存泄漏(以AndroidStudio开发工具为例)。
1、下载MAT(Eclipse Memory Analyzer)工具,windows64位网盘下载地址:http://pan.baidu.com/s/1pLlbOBD,或者通过官网下载:https://www.eclipse.org/mat/downloads.php,下载完毕后解压即可,目录结构如下:
2、模拟内存泄漏的场景,源码如下,启动退出三次app即可。
代码结构如下
MainActivity.java
package androidstudy.androidartstudy05;
import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import androidstudy.androidartstudy05.manager.TestManager;
public class MainActivity extends AppCompatActivity implements TestManager.OnDataArrivedListener {
private static final String TAG = "MainActivity";
private static Context sContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sContext = this;
TestManager.getInstance().registerListener(this);
}
private synchronized void testANR() {
SystemClock.sleep(30 * 1000);
}
private synchronized void initView() {
}
@Override
public void onDataArrived(Object data) {
Log.i(TAG, data.toString());
}
}
TestManager.java
package androidstudy.androidartstudy05.manager;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Administrator on 2016/7/19.
*/
public class TestManager {
private List<OnDataArrivedListener> mOnDataArrivedListeners = new ArrayList<OnDataArrivedListener>();
private static class SingletonHolder {
public static final TestManager INSTANCE = new TestManager();
}
private TestManager() {
}
public static TestManager getInstance() {
return SingletonHolder.INSTANCE;
}
public synchronized void registerListener(OnDataArrivedListener listener) {
if (!mOnDataArrivedListeners.contains(listener)) {
mOnDataArrivedListeners.add(listener);
}
}
public synchronized void unregisterListener(OnDataArrivedListener listener) {
mOnDataArrivedListeners.remove(listener);
}
public interface OnDataArrivedListener {
public void onDataArrived(Object data);
}
}
3、点击AndroidStudio界面的Monitor按钮打开DDMS界面,如下图所示,点击Dump HPROF file(红色框框标记)按钮导出一个hprof后缀的文件androidstudy.androidartstudy05.hprof保存到platform-tools下(放到此目录是为了下一步方便转换文件),我的路径为E:\Android\sdk\platform-tools
4、由于导出后的文件不能直接被MAT识别,所以需要通过hprof-conv命令转换一下,此命令是Android SDK提供的工具,位于platform-tools下,cmd命令切换到此目录后输入hprof-conv androidstudy.androidartstudy05.hprof androidstudy.androidartstudy05-conv.hprof命令回车,
会在platform-tools目录下生成一个androidstudy.androidartstudy05-conv.hprof文件,如下图:
5、打开MAT工具,导入转换后的文件androidstudy.androidartstudy05-conv.hprof,打开后界面如下:
6、点击“Histogram”按钮,展示界面如下,在红色框框中输入应用的包名androidstudy.androidartstudy05
7、通过下图结果可以看到MainActivity对象有三个(正常只会出现一个),很明显MainActivity存在内存泄漏
8、在MainActivity上点击右键->"Merge Shortest Paths To GC Roots"->"exclude all phantom/weak/soft etc.refrences"。
9、在打开的界面即可看到详细的引用详情
10、可以看到有三处引用了MainActivity对象,两处为单例对像列表(List<OnDataArrivedListener>)属性mOnDataArrivedListeners 持有,一处为静态变量private static Context sContext;持有