内存泄漏(二)
来源:互联网 发布:上海大剧院 座位 知乎 编辑:程序博客网 时间:2024/05/22 00:44
引言
首先我们先来写一个程序模拟一下内存泄漏,方法很多,上一篇安卓面试系列–内存泄漏(一)中我们讲了很多造成内存泄漏的原因,不知道大家还记不记得,不记得的话记得多看几遍,然后自己默写处出来。这里还是带大家简单过一遍吧,首先是单例模式的静态关键字和创建单例时需要传入的context,第二个是非静态内部类创建静态实例,第三个是Handler,第四个AsyncTask和线程,最后一个是一些资源未关闭,比如bitmap,cursor,ContentObserver。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void onclick(View view) { Intent intent = new Intent(this,SecondActivity.class); startActivity(intent); }}
public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(60000000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }}
- 下面我们从MainActivity跳到SecondActivity 然后从SecondActivity返回MainActivity,连续这样5次 ,最终返回MainActivity,按照常理来说,我们从SecondActivity返回MainActivity之后 SecondActivity就该被销毁回收,可实际可能并不是这样;
- SecondActivity有个子线程进行长时间的耗时操作,导致SecondActivity回收不了,重复几次后会导致SecondActivity有多个实例,导致内存泄漏。
查找内存泄漏
1、直接使用Android Studio的Monitor Memory查找
首先 在手机上运行程序,打开AS的 Minotor 界面 查看Memory 图像
点击 小卡车图标(图中1位置图标) 可以触发一次 GC
点击 图中2位置图标可以查看hprof文件
左边是 内存中的对象,在里面找 Activity 看存不存在我们希望已经回收的Activity 如果 出现我们期望已经回收的Activity,单击 就会在右边显示它的总的个数,点击右边的某个,可以显示 它的GC Roots的树关系图 ,查看关系图就可以找出发生内存泄漏的位置
2、利用MAT工具查找(重点)
首先打开AS中的Android Device Monitor工具 具体位置如下图:
打开后会出现如下的界面
先选中你要检测的应用的包名,然后点击下图画圈的地方,会在程序包名后标记一个图标
接下来要做的就是操作我们的app 来回跳转5次。之后点击下图的图标 就可导出hprof文件进行分析了
导出文件如下图所示:
-如果没有这个工具的,我这里提供这个网址供大家下载:MAT工具下载地址
界面如下图所示:
打开我们先前导出的hprof文件 ,不出意外会报下面的错误
这是因为MAT是用来分析Java程序的hprof文件的 与Android导出的hprof有一定的格式区别,因此我们需要把导出的hprof文件转换一下,sdk中提供给我们转换的工具 hprof-conv.exe 在下图的位置
- 接下来我们cd到这个路径下执行这个命令转换我们的hprof文件即可,如下图
其中 hprof-conv 命令 这样使用
hprof-conv 源文件 输出文件
比如 hprof-conv E:\aaa.hprof E:\output.hprof
就是 把aaa.hprof 转换为output.hprof输出 output.hprof就是我们转换之后的文件,图中 mat2.hprof就是我们转换完的文件。
接下来 我们用MAT工具打开转换之后的mat2.hprof文件即可 ,打开后不报错 如下图所示:
之后我们就可以查看当前内存中存在的对象了,由于我们内存泄漏一般发生在Activity中,因此只需要查找Activity即可。
点击下图中标记的QQL图标 输入 select * from instanceof android.app.Activity
类似于 SQL语句 查找 Activity相关的信息 点击 红色叹号执行后 如下图所示:
- 接下来 我们就可以看到下面过滤到的Activity信息了如上图所示, 其中内存中还存在 6个SecondActivity实例,但是我们是想要全部退出的,这表明出现了内存泄漏;
其中 有 Shallow size 和 Retained Size两个属性
- Shallow Size
- 对象自身占用的内存大小,不包括它引用的对象。针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。针对数组类型的对象,它的大小是数组元素对象的大小总和。
- Retained Size
- Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C, C就是间接引用),不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。
- Shallow Size
接下来 右击一个SecondActivity
- 选择 with all references,打开如下图所示的页面
- this
0代表内部类的意思,也就是一个内部类引用了Activity而this 0又被 target引用 target是一个线程,原因找到了,内存泄漏的原因 就是 Activity被 内部类引用 而内部类又被线程使用 因此无法释放,我们转到这个类的代码处查看
总结
好了,以上就是关于安卓中最常用的两种查找内存泄漏的工具,具体流程的话不用死记硬背,面试的时候就说会使用Android Studio的Monitor Memory和MAT工具查找内存泄漏就可以了,具体里面的内容问的也不多,毕竟只是一个工具而已,主要还是要在敲代码的过程中避免内存泄漏,真正有了内存泄漏,能想起来有这两个东西就可以了。
- 内存泄漏(二)
- 浅谈内存泄漏(二)
- 浅谈内存泄漏(二)
- 浅谈内存泄漏(二)
- 浅谈内存泄漏(二)
- 使用MAT分析内存泄漏(二)
- 使用MAT分析内存泄漏(二)
- 内存泄漏和溢出整理(二)
- 内存泄漏学习(二)工具介绍
- Android 内存泄漏总结(二)
- 【Opencv学习(二)】内存溢出和内存泄漏总结
- Android内存泄漏(Handler造成的内存泄漏(二))
- JAVA内存泄漏分析(二)
- Java的内存泄漏(二)
- UIWebView内存泄漏解决办法(二)
- 浅谈内存的泄漏(二)
- 内存泄漏分析二-线程
- 使用Memory Analyzer tool(MAT)分析内存泄漏(二)
- SQL Union和SQL Union All用法
- Git命令
- HDU 1198 Farm Irrigation (BFS)
- Android 学习书单
- UVA 10256 The Great Divide(凸包应用 即凸包+线段相交判定+点是否在凸包内判断)
- 内存泄漏(二)
- 欢迎使用CSDN-markdown编辑器
- sourceinight4使用
- 操作系统-内存管理-内存与外存的对换(swapping)
- tensorflow学习笔记(一) --- 一元线性模型
- Team的创建和规划
- 希尔排序
- poj 3317 Stake Your Claim(极大极小搜索经典 a-b+剪枝+记忆化dp)
- java学习记录(1)-jvm安装