博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Andriod项目内存泄漏流程
阅读量:5953 次
发布时间:2019-06-19

本文共 2865 字,大约阅读时间需要 9 分钟。

案例:(本篇还以上篇案例为例子)

public class CommUtil {    private static CommUtil instance;    private Context context;    private CommUtil(Context context) {        this.context=context;    }    public static CommUtil getInstance(Context context){        if(null==instance){            instance=new CommUtil(context);        }        return instance;    }}复制代码
public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        CommUtil instance = CommUtil.getInstance(this);    }}复制代码

(将Activity的实例被一个单例对象所持有,在旋转屏幕的时候造成内存泄漏) 将项目运行起来 打开Android Profiler 观察Memory 并且试着多次旋转屏幕就会发现内存一直在增高

点击Dump java Heap生成一份内存快照hprof文件

Dump java Heap: 点击就会生成app运行内存快照.hprof文件 然后将APP完全退出 重新启动 打开Android Monitor 点击Dump java Heap点击生成一份还没操作前(旋转屏幕)的内存快照hprof文件(为以后作对比用) 现在就已经生成好了2份hprof文件 一份是没有旋转过屏幕的 一份是旋转过屏幕多次的 然后选中Android Studio 最左边的Captures 进行将hprof文件导出(因为MAT不支持Android Studio生成的未经转换的hprof文件 在导出过程中Android Studio会为我们转换好)

MAT上场了

安装 Memory Analyzer 插件

导入生成的两个文件

这个时候可能会报错

Unknown HPROF Version (JAVA PROFILE 1.0.3) (java.io.IOException) 这是应为studio生成的.hprof文件和eclipse支持的.hprof文件格式问题

转换格式: 进入SDK目录输入 hprof-conv inputfilepath outputfilepath之后从新导入即可

先来看看MAT都有哪些功能:

Overview视图 该视图会首页总结出当前这个Heap dump占用了多大的内存,其中涉及的类有多少,对象有多少,类加载器,如果有没有回收的对象,会有一个连接,可以直接参看(图中的Unreachable Objects Histogram)。

histogram视图: 列举内存中对象存在的个数和大小 Dominator tree视图:该视图会以占用总内存的百分比来列举所有实例对象,注意这个地方是对象而不是类了,这个视图是用来发现大内存对象的 Top Consumers: 该视图会显示可能的内存泄漏点 Duplicate Classes: 该视图显示重复的类等信息 本次重点围绕histogram视图讲解 其他3个视图也只是给我提供一些可能会造成内存泄漏的信息 点击打开Histograms视图

打开下面的面板Navigation History 选中histogram右键add to Compare Basket 添加到比较容器中(2个hprof文件都做以上同样的操作 将histogram 添加到比较容器中)

这时比较容器中就有2份hprof文件 一份未做任何操作 一份做了多次旋转屏幕(注意:导入的比较容器的顺序很重要 不然后面的数据看起来让人费解)然后点击Compare the results (红色感叹号)进行比较

通过比较后就会生成一个比较结果表ComPared Tables

但是这个表内容太多 如何快速过滤出我们与我们自己写的项目内容有关的呢 接着在Class Name 输入我们的项目包名

通上图就明显看出经过2个hprof比较 在我们操作了旋转多次屏幕后MainActivity的实例增加了然后我们就去分析下该hprof文件是什么导致MainActivity内存泄漏了

在Class Name处可以根据输入的类名去查找对应的对象实例(比如我们输入MainActivty):

Objects:实例个数 Shallow Heap:所占内存大小 Retained Heap:释放后能回收多少内存 通过上图看到了MainActivtiy在旋转屏幕后产生了2个实例 再去观察MainActivtiy具体被哪些对象引用呢 鼠标选中MainActivtiy 实例右键 选择with incoming references:

看到MainActivty被引用的地方这么多 而且一屏还显示不完 我们又如何去判断是哪个导致内存泄漏的呢 MAT还有一个功能 就是通过遍历GC Root树去将那些有可能被GC回收的实例 将他们去除(备注:在GC Root树中能找到的对象绝对不存在有内存泄漏的实例 因为他们在运行时会被回收的嘛 只有找不到的那些才是)鼠标右键:

看那些单词就知道是什么意思 (排除 软引用 弱引用 虚引用) 最后我们就看到了Commutil的instance引用了MainActivty实例 而后旋转屏幕的时候 系统又创建了一个 所以有2个引用着MainActivtiy的实例 造成的内存泄漏:

然后就去修改代码: public class MainActivity extends AppCompatActivity {

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); CommUtil instance = CommUtil.getInstance(getApplicationContext());  }}复制代码

转载于:https://juejin.im/post/5c9895c4f265da60e65ba2af

你可能感兴趣的文章
Redis集群搭建与简单使用
查看>>
jquery的选择器之-表单对象属性过滤选择器
查看>>
Linux根目录下的各个子目录的作用
查看>>
上:Spark VS Flink – 下一代大数据计算引擎之争,谁主沉浮?
查看>>
HA脑裂问题
查看>>
DHCP 实例配置
查看>>
19. yum 常用命令《Mr.Robot》
查看>>
linux基础-权限管理,手工添加用户,umask,bash配置文件
查看>>
AD灾难恢复情景及方案
查看>>
mysql 导出
查看>>
Openstack M版快速配置(二)--刷数据库
查看>>
sed
查看>>
Failed to execute goal org.apache.maven.plugins:ma
查看>>
如何利用华为交换机配置SSH登录
查看>>
数据挖掘的产品
查看>>
2013.8.4thinkPHp学习
查看>>
cygwin图文安装教程
查看>>
去小机化思维(二)--【软件和信息服务】2015.03
查看>>
华为交换机的端口hybrid端口属性配置
查看>>
算法学习之归并排序(java实现)
查看>>