AndroidStudio + MAT 内存泄漏分析

阅读: 评论:0

AndroidStudio + MAT 内存泄漏分析

AndroidStudio + MAT 内存泄漏分析

一概要:

内存泄漏是一些已经不使用的对象,依然占有内存且垃圾回收机制不法回收它们。最终导致常驻内存越来越大

,影响到程序的性能。

在Android 虚拟机中,采用Mark-Sweep方式实现垃圾回收。Mark标记,Sweep检测。虚拟机会从GC Roots开始

遍历,如果某个节点无法找到一条到达GC Roots的路径,则表示该引用无效,可以被回收。内存泄漏就是存在一些

不好的调用,导致一些无效的引用于GC Roots相连,无法被回收。

知道了原因,我们理应在开发中尽量避免这些。但是万一发生了(代码又不是一个人写的),我们要准确找出它们。

所以我们就要用到检测内存泄漏的工具。

转载:

二使用:

实例代码(我们进入主页面后,点击启动TestSecondActivity,然后按返回退出):

   Intent intent2 = new Intent(MainActivity.this, TestSecondActivity.class);startActivity(intent2);

public class TestSecondActivity extends AppCompatActivity{@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {Create(savedInstanceState);setContentView(R.layout.activity_testsecond);Runnable runnable = new Runnable() {@Overridepublic void run() {LogUtil.i("TestSE", "thread:" + Thread.currentThread() + "start");try{Thread.sleep(80000l);}catch (Exception e){}LogUtil.i("TestSE", "thread:" + Thread.currentThread() + " end");}};new Thread(runnable).start();}
}

我们会通过两种方式,来检测内存泄漏:

#使用MAT用具查找

1,首先打开Android Studio中的Android Device Monitor如下图。


2,打开后会出现下面界面,选中你要检测应用的包名,然后点击下图画圈的地方(Update Heap),会在程序包

名后标记一个图标


3,接下就是我们的操作,,重复启动回退TestSecondActivity 两次,然后再点下图画圈地方(Dump HPROF file)

生成hprof文件。


生成的hprof文件。


4,因为MAT是用于分析java hprof的工具,我们生成的是Android属性的hprof文件,所以我们要转化一下(我将刚刚

生成的文件重名android.hprof)。

Android Sdk中为我们提供了工具&#。


转化成了java属性的文件java.hprof。

5,使用MAT打开hprof文件,(如果还没有安装MAT的,先下载安装:/)。


打开后如图:


6,之后我们查看内存中的对象,由于我们的内存泄漏一般都发生在Activity中所以我们之查找Activity即可。

点击下图中的QQL图标,输入select * from instanceof android.app.Activity,类似于SQL语句。红色感叹号为执行按钮。

#内存中有两个TestSecondActivity,但是我们已经退出了TestSecondActivity,说明发生了内存泄漏。

#上面有两个属性。Shallow Size对象自身占用大小,不包括引用。Retained Size对象自身大小+ 直接或间接引用对象

的大小。

7,右击TestSecondActivity,—— Path to GC Roots——All Reference。


看到this$0引用了这个Activity,this$0表示内部类意思。Activity被一个内部类引用,而这个内部类又被target(Thread)引用。

从上面的代码可知:

TestSecondActivity中有内部类runnable,而runnable被Thread使用。工作线程Thread需要sleep 80秒。所以导致

TestSecondActivity无法释放。

解决方法。我们在Activity onDestroy中shutdown 线程Thread就可以了(当然先把Thread变成全局变量)

#直接使用Android Studio上的Monitor Memory查找

1,依然是利用上面的代码,运行程序,打开Android Studio的Monitor界面,查看Memory图像。


2,点击下卡车图标(图中1),可以执行一次GC;点击图中2的位置,可以查看hprof文件。(依次点击1,2)

3,查看结果


#同样监听到了TestSecondActivity的内存泄漏。

三注意

Android中内存引起内存泄漏的常见使用。

1,static变量引起的内存泄漏。

因为static生命周期是类加载时开始,类卸载结束。也就是说static变量在程序死亡时才结束。而如果static变量引用

Activity,那么Activity的资源将一直得不到释放。造成内存泄漏。

解决方法,如果需要Context对象,尽量使用getApplicationContext。假如必须使用Activity那么最好在onDestroy方

法中,将Activity引用设置为null。

2,线程造成的内存泄漏。

类似于上面的例子,线程执行时间长,即使Activity结束了任然在执行。因为new Thread生成一个匿名内部类(内部

类的创建必须依靠外部类),因此握有Activity实例,Activity无法释放。AsyncTask更为严重,因为AsyncTask维持一

个生命周期。

解决方法:合理安排线程,控制线程在Activity结束时结束。

3,Bitmap占用过多的内存。

Bitmap解析需要占用内存,但是Android只提供了8M内存给Bitmap,如果Bitmap过多且不能及时的回收。则会造成内

存溢出。

解决方法:及时recycle,加载图片前先适当的压缩图片。

4,资源未被及时关闭造成内存泄漏

例如Cursor,没有及时关闭,会因持有Activity引用,造成内存泄漏。

解决方法:在onDestroy中及时的关闭。

5,Handler的使用

Handler对象会发送Message到MessageQueue,Looper对象会轮询MessageQueue对象去除Message执行。如果

Message对象长时间未被取出执行。则Message对象持有Handler对象,Handler对象持有Activity(可能)。造成泄漏。

解决方法,在onDestroy中,Handler removeMessage。


欢迎指正!

本文发布于:2024-02-04 15:58:21,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170711094856890.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:内存   AndroidStudio   MAT
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23