简介
Memory Profiler是Android Profile中的一个组件,Android Profile是Android Studio 3.0 替换之前的Android Monitor工具的,主要用来观察内存,网络,cpu,今天主要介绍Memory Profiler,他可以让你观察出内存抖动和内存泄露
如何进入Memory Profiler
Memory Profiler主面板介绍
- 标号1处:手动触发GC
- 标号2处:查看当前Java堆的情况
- 标号3处:查看一段时间内的Java堆的变化
关于顶部类型的介绍
java:java代码占用的内存
Native:c/c++代码分配的内存
Graphics:图像缓存的内存
Stack:栈内存
Code:代码内存分配
Other:其他类型的内存
Allocated:java对象分配的个数
如何查找内存泄露
首先你需要写一个内存泄露的代码
public class ActivityOne extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_one);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
}
}, 100000);
}
}
比如这个Activity,我写了一个Handler的内存泄露,然后你启动这个activity然后关闭这个Activity,重复几次之后,手动触发GC,然后抓取堆内存的分布情况
点击Dump Java Heap,然后就会出现下面这个界面
看标号1处,有几个取值分别介绍一下
- App heap: app的堆分配
- Image heap: 图像的堆分配
- Zygote heap: 这个按照官方的解释是来自安卓系统fork进程的地方产生的写数据备份
看标号2处,有三个取值分别代表
- Arrange by class:基于类名对所有分配进行分组
- Arrange by package:基于包名对类进行分组
- Arrange by callstack:将所有的分配,分组到对应的调用栈内
看标号3处,分别的意思是
Class Name : 类名
Allocation:对象的个数
Native Size :C层内存的大小byte
Shallow Size:java层的内存大小
Retained Size :这个是这个对象的总大小*对象的个数
我们选择按包名分组
然后找到我们的包
按照正常情况内存中不应该存在ActivityOne的对象,因为我们已经退出销毁了,但是这里我们能看到,还存在ActivityOne的对象并且还有3个,也就是说这个ActivityOne对象内存泄露了
我们点击ActivityOne这个类名,会跳出instance View,显示该类的每一个实例
其中包括几个信息
- Depth:GC Root 到达该实例的最短路径
- Native Size: c/c++层中内存的大小(bytes)
- Shallow Size:java层内存大小(bytes)
- Retained Size:这个类中所引用到的对象的总大小(bytes)
然后点击其中的一个引用,会弹出一个References的页面,他显示每个对象的引用,然后我们在里面查找异常的引用
在这里我们看到大部分都是系统层面的引用,只有一个通过this引用了ActivityOne,我们点进去发现是MessageQueue持有了引用,根据我们的经验就是Handler造成的内存泄露,然后我们Jump To Source,发现就是这段代码造成了内存泄露
这样就完成了一次内存泄露的探索