运用Android Studio对程序进行内存分析和调试
一、界面介绍
打开Android Studio看下它的界面,在最底下可以找到 Android Monitor标签,点击打开它,如下图所示。
第一个Memory就是用来监测当前程序的内存使用状态的,我们只看这个。有的人打开后可能只能看到Logcat模块,不要急,在logcat的最右边找找,看有没有一个小图标,有就点开它,立马就会出现Monitors模块。
看看下面这个部分:
代表监视器目前监测的手机。
这里用来显示监视器正在监测的进程,点击右边的下拉箭头,可以选中某一个进程进行监视。
有的人会出现这种现象,打开monitor模块,发现所有的monitor全部disable,这样你可以查看下刚刚提到的两个部分是否是[DISCONNECT]和[DEAD]的:
如果是的话,就去点右边的下拉箭头,选中一个正常的设备和进程就行了。如果还解决不了,那么参考这篇文章http://blog.csdn.net/yangxi_pekin/article/details/51860998不过我用的是模拟器,重启下就好了。
还要提一下,如果你发现CPU和Network monitor能够正常工作,但Memory和GPU monitor is disabled,那么尝试着点击旁边的暂停按钮,多点几次就好了
相关链接:http://stackoverflow.com/questions/38202637/memory-monitor-is-disabled-in-android-studio
二、Memory 界面
五个按钮的作用从左到有分别是:
- (Enabled)暂停内存监视器的工作
- (Initial GC)启动垃圾回收,一般在Dump Java Heap之前用来清楚无用对象。
- (Dump Java Heap)生成一份当前内存使用情况的日志
- (Start Allocation Tracking)记录一段区间内各个线程各个方法的内存分配情况
- (Memory monitor help)查看帮助文档
说明一下Start Allocation Tracking,先点击它启动这个功能,然后在手机上做一些操作,然后再点一次就会结束此次内存的记录。最后你会发现AS自动生成了alloc文件。
图中记录了四个线程在我操作手机时在内存分配的堆空间。
三、内存调试
现在用代码模拟一个内存泄漏程序:
package com.phoenix.l_ui;
import android.app.Activity;
import java.util.LinkedList;
import java.util.List;
/**
* Created by developer on 16-10-21.
*/
public class Cache {
private static Cache cache = null;
private List<Activity> activityList = new LinkedList<Activity>();
public static Cache getInstance() {
if (cache == null) {
synchronized (Cache.class) {
if (cache == null) {
cache = new Cache();
}
}
}
return cache;
}
public void addAty(Activity aty) {
activityList.add(aty);
}
}
新建一个单例子类,里面的activityList用于存储程序的MainActivity
package com.phoenix.l_ui;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
Object[] objs = new Object[1000]; //使得内存泄漏更明显
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Cache.getInstance().addAty(MainActivity.this);
}
}
不停的旋转手机屏幕,MainActivity本应该不停的销毁重建,但是每次创建MainActivity时,cache就会自动将MainActivity加入引用,所以MainActivity是不会销毁的,这样在程序里面就会存在多个activity实例造成内存泄漏。
看旁边的英文提示,可以知道内存使用量是在增加的,虽然有下降,单总体来说是上升的,我们可以猜测发生了内存泄漏,所以我们需要把生成一份当前内存的日志文件。
启动init GC,然后再Dump Java Heap,AS会自动生成.hprof文件,如下图显示:
把上图显示的 Class List VIew切换到 Package Tree View,进入应用的包名中,可以看到MainActivity的实例有41个:
这就是Memory的基本用法,不过一般情况下我们是不知道到底是什么地方发生了内存泄漏,所以需要dump Java heap次内存日志,对比日志之间的差异,看是什么地方的对象引用数量增加的比较多,这样就可以分析出哪里需要优化。