之前,我们一直都在使用Android Device Monitor对我们的应用进行各种分析,也建立了很深厚的感情,而如今,Android Device Monitor 已在 Android Studio 3.1 中弃用,并已从 Android Studio 3.2 中移除,也意味着它即将要退役,离我们越来越远了,为了纪念这位曾经对App做出巨大贡献的应用,让我们回顾一下它的事迹!
准备工作
- 在Android SDK路径下打开tools双击monitor打开Android Device Monitor
- 下载MAT工具并安装
Android Device Monitor
打开后它的主页面如图一,如果有些窗格没有展示出来,可以点击window-Reset Perspective-Yes重置下配置,或者点击window-Show View选择自己想要展示的窗格
Devices
设备列表如图二所示,选择某应用后,红色框内的图标就会点亮,供您使用,他们的具体信息从左到右介绍如下:
- Debug Process:调试进程,该按钮一直处于灰色状态不能点击
- Update Heap:更新堆信息,点击后它,结果将会在Heap窗格中展示
- Dump HPROF file:获取hprof文件(常用),官方推荐使用新工具CPU Profiler
- Cause GC:垃圾回收
- Update Threads:更新线程信息,结果在Threads中展示
- Start Method Profiling:启动方法分析,官方推荐使用新工具CPU Profiler
- Stop Process:停止进程
- Screen Capture:屏幕截图
- Dump View Hierarchy for UI Automator:视图层级转储(常用),官方推荐使用新工具Layout Inspector,用Layout Inspector查看视图层级时,如果您的设备没有安装Google Play商店且已获得root权限才能看到正在运行的应用,否则,只能看到正在运行的可调试应用。如果您想在非root手机上查看正在运行的不可调试应用视图,建议您使用Dump View Hierarchy for UI Automator尝试一下
- Capture System Wide Trace:捕获系统信息
- Reset adb:重置安卓调试桥
-
Start OpenGL Trace:开启OpenGL跟踪
Dump HPROF file
此功能主要用来生成.hprof文件,对于该文件的分析,还需要工具Eclipse Memory Analyzer打开才行。monitor生成的.hprof文件并不是标准的、MAT可识别的文件,因此,需要我们把.hprof转成标准的文件后,才能使用MAT工具进行分析,转换步骤如下:
- 打开命令行工具
- 输入hprof-conv -z A.hprof B.hprof,如果提示命令hprof-conv用不了的话,请切换到android sdk/platform-tools后再操作
- A.hprof为转换前的文件
- B.hprof为转换后的文件
在这里,我们创建一个项目,故意让一个单例类SingleInstance持有SingleInstanceActivity对象导致内存泄漏,接着使用DDMS工具生成.hprof文件,然后再使用上面的命令换成标准的.hprof文件后,我们就可以进入MAT的世界了!
该测试项目只有三个Java文件如下
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onSingleInstance(View view) {
Intent intent = new Intent(this, SingleInstanceActivity.class);
startActivity(intent);
}
}
SingleInstance.java
public class SingleInstance {
private static Context context;
private static SingleInstance singleInstance;
private SingleInstance() {
}
public static SingleInstance getInstance(Context ctx) {
if (singleInstance == null) {
context = ctx;
singleInstance = new SingleInstance();
}
return singleInstance;
}
}
SingleInstanceActivity.java
public class SingleInstanceActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_single_instance);
SingleInstance.getInstance(this);
}
}
运行App后,先点击Dump HPROF file一次获取没有产生内存泄漏的unml.hprof文件,接着依序打开SingleInstanceActivity-点击返回键,在DDMS中频繁点击GC,再继续获取有内存溢出的ml.hprof文件,然后将unml.hprof转换成unml_stantard.hprof文件,将ml.hprof转换成ml_stantard.hprof文件。
MAT
使用MAT打开我们刚才生成的unml_stantard.hprof文件,打开步骤:File->Open Heap Demp,打开后默认展示如图三所示,这个时候我们点击Histogram如图四所示,然后在红框这个地方输入我们的包名敲回车如图五所示,红框这个地方显示,只存在一个实例,也就是MainActivity,同样的操作,我们在ml_stantard.hprof看一下,ml_stantard的Histogram如图六所示,这个时候我们发现SingleInstanceActivity还存在呢,内存泄漏也就产生了,无论我们GC多少次,由于该对象被单例对象持有,而单例对象生命周期和应用一致,所以导致SingleInstanceActivity不能回收。
最后,我们简单总结一下整个操作流程如下:
- 启动应用
- 打开monitor,选择应用
- 点击Dump HPROF file生成.hprof文件
- 打开怀疑内存泄漏的页面后,关闭,频繁GC操作
- 再次生成.hprof文件
- 将两个.hprof文件转换成标准的文件
- 使用MAT工具打开.hprof文件
其实,整个操作流程还是挺麻烦的,读者朋友们了解一下就可以了,因为Google还提供了另一种更加便利的方式,想了解的朋友可以看一下上一篇文章Android性能优化—内存泄漏分析(一)