文档章节

Android程序的内存泄漏与规避方法

 我爱网王
发布于 2015/01/12 11:30
字数 1966
阅读 48
收藏 1

  Android应用程序中内存使用的问题经常容易被忽视,在传统的编程语言中(例如C语言),回收内存的任务是由程序本身来完成的,程序可以显式分配和释放变量所占用的内存。Android[1]应用程序采用Java编程语言编写,而Java区别于其他语言的一个重要优点就是它通过垃圾收集器(Garbage Collection,GC) 自动管理内存的回收,Java程序员只需通过内存分配操作创建对象,而无须关心对象占用的空间是如何被收回的。因此很多程序员认为在Java中不必担心内存泄漏的问题,然而实际并非如此,Java中仍然存在着内存泄漏。Android应用程序运行在嵌入式系统中,而嵌入式系统中内存的总量非常有限,因此如何合理地规避“内存泄露”问题也就显得十分关键。

  1 造成Android应用程序内存泄漏的原因

  1.1 引用没释放造成的内存泄露

  (1) 注册没有取消造成的内存泄漏

  这种Android的内存泄露比纯Java的内存泄漏还要严重,因为其他一些Android程序可能引用系统的Android程序的对象(比如注册机制)。即使Android程序已经结束了,但是别的应用程序仍然还有对Android程序的某个对象的引用,泄漏的内存依然不能被垃圾回收。

  (2) 集合中对象没有关闭造成的内存泄漏

  通常把一些对象的引用加入到了集合中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,慢慢地这个集合就会越来越大。如果这个集合是静态的话,那情况就会更严重。

  1.2 资源对象没有关闭造成的内存泄漏

  资源对象比如Cursor、File文件等往往都用了一些缓冲,在不使用的时候应该及时关闭它们,以便它们的缓冲及时回收内存。这些缓冲不仅存在于Java虚拟机内,还存在于Java虚拟机外,如果仅仅是把它的引用设置为空,而不关闭它们,那么往往会造成内存泄漏。

  一些不良代码造成的内存压力原因如下:

  ◆ Bitmap没有调用recycle( );

  ◆ 构造Adapter时,没有使用缓存的convertView;

  ◆ ThreadLocal使用不当;

  ◆ 其他。

  2 内存泄漏的检测及定位

  2.1 内存泄漏的检测

  Android应用程序是基于虚拟机的,其内存管理都是由Dalvik[2]代为管理,GC的回收不是及时的。一个正常的应用程序在其运行稳定后其内存的占用量是基本稳定的,不应该是无限制的增长。同样,对任何一个类的对象的使用个数也有一个相对稳定的上限,不应该是持续增长的。当我们持续地观察某个应用程序运行过程中使用内存的大小和各实例的个数时,如果内存的大小持续增长,则说明系统存在内存泄漏的问题;如果特定类的实例对象个数随时间而增长,则说明这个类的实例可能存在泄漏情况。比如一个Activity被关掉之后,其内存的引用对象会在下次GC回收[3]的时候通过回收算法计算,如果这部分内存已经属于可回收的对象,那么这些垃圾对象会被一并回收,内存未泄漏趋势图如图1所示。

  图1 内存未泄漏趋势图

  内存泄漏趋势图如图2所示。在重复打开关闭某个应用程序的时候,内存一直在向上爬升,也就是说每次关闭这个Activity的时候,有些应该释放的内存并没有被释放掉。由此我们可以确定这个应用程序存在着内存泄漏的问题。

  图2 内存泄漏趋势图

  2.2 内存泄漏的位置定位

  查找内存泄漏一种比较彻底的方法就是代码走查,我们可以一行一行地分析对象的创建去留等等[4],但会很耗时间也比较迷茫。这里可以通过Eclipse Memory Analyzer Tool(MAT)工具来定位内存泄漏的位置,该方法只适用于Java层的查找,对C/C++没用,也就是说只针对于被虚拟机来管理的进程和内存。MAT的解析文件是。hprof文件,这个文件里面存放了某进程的内存快照,MAT通过解析。hprof文件就会自动生成一个内存泄漏推测报告,通过分析这个报告就可以准确定位到有可能存在内存泄漏的具体位置。

  然而,还有一些内存泄澳门赌博漏通过MAT是查不出来的,比如native的代码,对C/C++是无能为力的,对于这些问题本文并没有做过多的研究。

  3 规避内存泄漏的方法

  在编写应用程序的过程中,对于BraodcastReceiver、ContentObserver、FileObserver在Activity onDestory或者某类声明周期结束之后一定要注销掉,否则这个Activity类会被系统强引用,不会被内存回收。

  在定义成员变量时,不要直接对Activity进行引用而作为成员变量。如果不得不这么做,那么可以用private Weak Reference mActivity来声明。同样,对于Service等其他有自己声明周期的对象来说,直接引用都需要谨慎考虑是否会存在内存泄漏的可能。

  在应用程序中,很多内存泄漏是由于循环引用而造成的,比如a中包含了b,b中包含了c,c中又包含a,这样只要一个对象存在,那么其他对象肯定会一直常驻内存。因此,在编写应用程序时要从逻辑上来分析是否需要这样的设计。

  Bitmap对象不再使用时,调用recycle()方法释放内存。如果一个Bitmap对象比较占内存,当它不再被使用的时候,可以调用Bitmap.recycle()方法回收此对象的像素所占用的内存,这个不是必须的,可视情况而定。

  还要注意释放对象的引用。当一个生命周期较短的对象A,被一个生命周期较长的对象B保有其引用的情况下,在A的生命周期结束时,要在B中清除掉对A的引用。

  4 内存监测工具DDMS和内存分析工具MAT

  4.1 内存监测工具DDMS

  我们在开发Android应用程序时,很容易造成内存的泄漏,这时需要一些工具来帮助我们检查代码中是否存在会造成内存泄漏的不良代码。在Android tools的DDMS里面带有一个内存监测工具Heap,用它来监测应用程序使用内存的情况,这里需要和Eclipse配合使用。利用 Heap工具监测应用进程使用内存情况的方法如下:

  ① 首先启动Eclipse,切换到DDMS透视图,并确认Devices视图、Heap视图都已打开。将要测试的设备(比如手机)通过USB数据线连接到电脑上,连接成功后,会在DDMS的Devices视图界面中显示手机设备的序列号,以及设备中正在运行的部分进程信息。

推荐阅读:http://blog.sciencenet.cn/blog-2094140-857770.html

© 著作权归作者所有

粉丝 0
博文 6
码字总数 11245
作品 0
武汉
私信 提问
Android内存泄漏以及解决办法

Android程序开发中,如果一个对象已经不需要被使用了,本该被回收时,而这时另一个对象还在持有对该对象的引用,这样就会导致无法被GC回收,就会出现内存泄漏的情况。 内存泄漏时Android程序...

lanyu96
2018/11/09
24
1
Android内存优化(六)LeakCanary使用详解

相关文章 Android性能优化系列 Java虚拟机系列 1.概述 如果使用MAT来分析内存问题,会有一些难度,并且效率也不是很高,对于一个内存泄漏问题,可能要进行多次排查和对比。 为了能够简单迅速...

刘望舒
2017/09/10
0
0
Android Application的作用

学习android挺长时间了,但是对于Appliction还不是很了解。今天花一些时间研究了一下Application。 What is Application Application和Actovotu,Service一样是android框架的一个系统组件,当...

程序袁_绪龙
2014/10/05
137
1
Android 系统开发_内存泄漏篇 -- "内存泄漏"的前世今生

基础了解 什么是内存泄漏? 内存泄漏是当有程序不再使用到的内存时,释放内存失败而产生了无用的内存消耗。内存泄漏并不是指物理上的内存消失,这里的内存泄漏是指由程序分配的内存,由于程序...

北辰丨丶
02/18
13
0
微信 Android 终端内存优化实践

前言 内存问题是软件领域的经典问题,平时藏得很深,在出现问题之前没太多征兆。而一旦爆发问题,问题来源的多样、不易重现、现场信息少、难以定位等困难,就会让人头疼不已。 微信在过去 N ...

北辰丨丶
03/01
37
0

没有更多内容

加载失败,请刷新页面

加载更多

代理模式之JDK动态代理 — “JDK Dynamic Proxy“

动态代理的原理是什么? 所谓的动态代理,他是一个代理机制,代理机制可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成,通过代理可以有效的让调...

code-ortaerc
今天
5
0
学习记录(day05-标签操作、属性绑定、语句控制、数据绑定、事件绑定、案例用户登录)

[TOC] 1.1.1标签操作v-text&v-html v-text:会把data中绑定的数据值原样输出。 v-html:会把data中值输出,且会自动解析html代码 <!--可以将指定的内容显示到标签体中--><标签 v-text=""></......

庭前云落
今天
8
0
VMware vSphere的两种RDM磁盘

在VMware vSphere vCenter中创建虚拟机时,可以添加一种叫RDM的磁盘。 RDM - Raw Device Mapping,原始设备映射,那么,RDM磁盘是不是就可以称作为“原始设备映射磁盘”呢?这也是一种可以热...

大别阿郎
今天
12
0
【AngularJS学习笔记】02 小杂烩及学习总结

本文转载于:专业的前端网站☞【AngularJS学习笔记】02 小杂烩及学习总结 表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng-repeat="x in names | orderBy ......

前端老手
昨天
16
0
Linux 内核的五大创新

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来。Linux内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大...

阮鹏
昨天
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部