Android 5.0的内存泄漏的后果到底是怎么回事?有什么后果

Android内存泄漏终极解决篇(下)
作者:Huang_Cai_Yuan
字体:[ ] 类型:转载 时间:
这篇文章主要为大家介绍了Android内存泄漏的相关资料,哪些写法容易造成内存泄漏,该如何解决?感兴趣的小伙伴们可以参考一下
在 中我们介绍了如何检查一个App是否存在内存泄漏的问题,本篇将总结典型的内存泄漏的代码,并给出对应的解决方案。内存泄漏的主要问题可以分为以下几种类型:
静态变量引起的内存泄漏
非静态内部类引起的内存泄漏
资源未关闭引起的内存泄漏
二、静态变量引起的内存泄漏
在java中静态变量的生命周期是在类加载时开始,类卸载时结束。换句话说,在android中其生命周期是在进程启动时开始,进程死亡时结束。所以在程序的运行期间,如果进程没有被杀死,静态变量就会一直存在,不会被回收掉。如果静态变量强引用了某个Activity中变量,那么这个Activity就同样也不会被释放,即便是该Activity执行了onDestroy(不要将执行onDestroy和被回收划等号)。这类问题的解决方案为:1.寻找与该静态变量生命周期差不多的替代对象。2.若找不到,将强引用方式改成弱引用。比较典型的例子如下:
单例引起的Context内存泄漏
public class IMManager {
private static IMManager mI
public static IMManager getInstance(Context context) {
if (mInstance == null) {
synchronized (IMManager.class) {
if (mInstance == null)
mInstance = new IMManager(context);
private IMManager(Context context) {
this.context =
当调用getInstance时,如果传入的context是Activity的context。只要这个单例没有被释放,这个Activity也不会被释放。
传入Application的context,因为Application的context的生命周期比Activity长,可以理解为Application的context与单例的生命周期一样长,传入它是最合适的。
public class IMManager {
private static IMManager mI
public static IMManager getInstance(Context context) {
if (mInstance == null) {
synchronized (IMManager.class) {
if (mInstance == null)
//将传入的context转换成Application的context
mInstance = new IMManager(context.getApplicationContext());
private IMManager(Context context) {
this.context =
三、非静态内部类引起的内存泄漏
在java中,创建一个非静态的内部类实例,就会引用它的外围实例。如果这个非静态内部类实例做了一些耗时的操作,就会造成外围对象不会被回收,从而导致内存泄漏。这类问题的解决方案为:1.将内部类变成静态内部类 2.如果有强引用Activity中的属性,则将该属性的引用方式改为弱引用。3.在业务允许的情况下,当Activity执行onDestory时,结束这些耗时任务。
内部线程造成的内存泄漏
public class LeakAty extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aty_leak);
public void test() {
//匿名内部类会引用其外围实例LeakAty.this,所以会导致内存泄漏
new Thread(new Runnable() {
public void run() {
while (true) {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}).start();
将非静态匿名内部类修改为静态匿名内部类
public class LeakAty extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aty_leak);
//加上static,变成静态匿名内部类
public static void test() {
new Thread(new Runnable() {
public void run() {
while (true) {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}).start();
Handler引起的内存泄漏
public class LeakAty extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aty_leak);
fetchData();
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
// 刷新数据
private void fetchData() {
//获取数据
mHandler.sendEmptyMessage(0);
mHandler 为匿名内部类实例,会引用外围对象LeakAty.this,如果该Handler在Activity退出时依然还有消息需要处理,那么这个Activity就不会被回收。
public class LeakAty extends Activity {
private TextView tvR
private MyH
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aty_leak);
tvResult = (TextView) findViewById(R.id.tvResult);
handler = new MyHandler(this);
fetchData();
//第一步,将Handler改成静态内部类。
private static class MyHandler extends Handler {
//第二步,将需要引用Activity的地方,改成弱引用。
private WeakReference&LeakAty& atyI
public MyHandler(LeakAty aty) {
this.atyInstance = new WeakReference&LeakAty&(aty);
public void handleMessage(Message msg) {
super.handleMessage(msg);
LeakAty aty = atyInstance == null ? null : atyInstance.get();
//如果Activity被释放回收了,则不处理这些消息
if (aty == null||aty.isFinishing()) {
aty.tvResult.setText("fetch data success");
private void fetchData() {
// 获取数据
handler.sendEmptyMessage(0);
protected void onDestroy() {
//第三步,在Activity退出的时候移除回调
super.onDestroy();
handler.removeCallbacksAndMessages(null);
四、资源未关闭引起的内存泄漏
当使用了BraodcastReceiver、Cursor、Bitmap等资源时,当不需要使用时,需要及时释放掉,若没有释放,则会引起内存泄漏。
综上所述,内存泄漏的主要情况为上面的三大类型,最终归结为一点,就是资源在不需要的时候没有被释放掉。所以在编码的过程中要注意这些细节,提高程序的性能。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具2011年8月 移动平台大版内专家分月排行榜第二2011年7月 移动平台大版内专家分月排行榜第二2011年3月 移动平台大版内专家分月排行榜第二
2012年8月 移动平台大版内专家分月排行榜第三2012年7月 移动平台大版内专家分月排行榜第三
2011年6月 移动平台大版内专家分月排行榜第二
2011年6月 移动平台大版内专家分月排行榜第二
本帖子已过去太久远了,不再提供回复功能。后使用快捷导航没有帐号?
只需一步,快速开始
查看: 4099|回复: 37
在线时间6 小时经验值226 最后登录注册时间帖子阅读权限50UID2447633
大学专科, 积分 224, 距离下一级还需 176 积分
TA的每日心情奋斗 14:04签到天数: 53 天[LV.5]常住居民I
G币674 最后登录注册时间
马上注册,结交更多机友,下载更多应用,让你轻松玩转手机。
已有帐号?   下载游戏和软件,请【】进入机锋市场!
Android5.0内存泄漏是谷歌在Android中留下的bug,本人是程序员,了解内存泄漏,个人认为sony应该没有修复内存泄漏的能力,已经升级至5.0的各位机油,你们的机器会不会出现内存泄漏出现的各种问题?
补充:下面是网上对内存泄漏的一个解释:内存泄漏,其实就是会导致设备内存被耗尽、而Android的内存回收机制无法自动清理,进而使得后台程序随机崩溃。内存泄漏最主要的表现就是RAM占用会随着开机使用时间增长而大幅增加,最后App会不断重载乃至崩溃。
在线时间44 小时经验值1613 最后登录注册时间帖子阅读权限80UID
研究生, 积分 1613, 距离下一级还需 87 积分
TA的每日心情奋斗 06:43签到天数: 60 天[LV.6]常住居民II
G币18 最后登录注册时间
占个沙发& && && && && &&&学习了
在线时间1 小时经验值329 最后登录注册时间帖子阅读权限50UID8742561
大学专科, 积分 329, 距离下一级还需 71 积分
TA的每日心情擦汗 22:33签到天数: 55 天[LV.5]常住居民I
G币146 最后登录注册时间
4.4就是这样
在线时间8 小时经验值2090 最后登录注册时间帖子阅读权限90UID
硕士, 积分 2090, 距离下一级还需 410 积分
TA的每日心情擦汗 10:32签到天数: 1079 天[LV.10]以坛为家III
G币8169 最后登录注册时间
感谢楼主的普及!
在线时间26 小时经验值945 最后登录注册时间帖子阅读权限70UID
学士, 积分 945, 距离下一级还需 155 积分
TA的每日心情奋斗 10:33签到天数: 68 天[LV.6]常住居民II
G币205 最后登录注册时间
在线时间0 小时经验值189 最后登录注册时间帖子阅读权限40UID
高中生, 积分 189, 距离下一级还需 11 积分
该用户从未签到
G币2 最后登录注册时间
楼主可否做个l39u 5.0的基带补丁&&感激不尽
在线时间1 小时经验值341 最后登录注册时间帖子阅读权限50UID
大学专科, 积分 341, 距离下一级还需 59 积分
TA的每日心情无聊 18:59签到天数: 12 天[LV.3]偶尔看看II
G币3 最后登录注册时间
安卓5.1就修复了,但索尼会不会推就不知道了
在线时间174 小时经验值2669 最后登录注册时间帖子阅读权限100UID
博士, 积分 2669, 距离下一级还需 831 积分
TA的每日心情怒 22:03签到天数: 3 天[LV.2]偶尔看看I
G币3 最后登录注册时间
好吧现在开两个后台来回切换都重新加载。
在线时间15 小时经验值444 最后登录注册时间帖子阅读权限60UID
大学本科, 积分 444, 距离下一级还需 256 积分
TA的每日心情怒 12:49签到天数: 67 天[LV.6]常住居民II
G币151 最后登录注册时间
xposed有个模块修复了内存泄露的bug,我安装了,具体没有体会是否修复了
在线时间591 小时经验值2147 最后登录注册时间帖子阅读权限90UID3657054
硕士, 积分 2147, 距离下一级还需 353 积分
TA的每日心情郁闷 09:27签到天数: 7 天[LV.3]偶尔看看II
G币1092 最后登录注册时间
紫夜零 发表于
xposed有个模块修复了内存泄露的bug,我安装了,具体没有体会是否修复了
求提供相应app模块
Powered by您所在的位置: &
Android内存泄漏的各种原因详解
Android内存泄漏的各种原因详解
eoe Android开发者社区
在Android开发过程中,最为让我们头疼的就是内存的泄露问题了,很可能你很小的一个错误都会引起内存的泄露,下面将为大家奉上引起内存泄露的解决方案。
1.资源对象没关闭造成的内存泄漏
资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。它们的缓冲不仅存在于
java虚拟机内,还存在于java虚拟机外。如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄漏。因为有些资源性对象,比如
SQLiteCursor(在析构函数finalize(),如果我们没有关闭它,它自己会调close()关闭),如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。因此对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null.在我们的程序退出时一定要确保我们的资源性对象已经关闭。
程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小,对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险。
示例代码:
Cursor&cursor&=&getContentResolver().query(uri...);&&if&(cursor.moveToNext())&{&&...&...&&}&
修正示例代码:
Cursor&cursor&=&null;&&try&{&&cursor&=&getContentResolver().query(uri...);&&if&(cursor&!=&null&&&cursor.moveToNext())&{&&...&...&&}&&}&finally&{&&if&(cursor&!=&null)&{&&try&{&&cursor.close();&&}&catch&(Exception&e)&{&&&&}&&}&&}&
2.构造Adapter时,没有使用缓存的convertView
以构造ListView的BaseAdapter为例,在BaseAdapter中提供了方法:
public View getView(int position, ViewconvertView, ViewGroup parent)
来向ListView提供每一个item所需要的view对象。初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的
view对象,同时ListView会将这些view对象缓存起来。当向上滚动ListView时,原先位于最上面的list
item的view对象会被回收,然后被用来构造新出现的最下面的list
item。这个构造过程就是由getView()方法完成的,getView()的第二个形参View convertView就是被缓存起来的list
item的view对象(初始化时缓存中没有view对象则convertView是null)。由此可以看出,如果我们不去使用
convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大。
ListView回收list item的view对象的过程可以查看:
android.widget.AbsListView.java --& voidaddScrapView(View scrap) 方法。
示例代码:
public&View&getView(int&position,&ViewconvertView,&ViewGroup&parent)&{&&View&view&=&new&Xxx(...);&&...&...&&return&&&}&
修正示例代码:
public&View&getView(int&position,&ViewconvertView,&ViewGroup&parent)&{&&View&view&=&null;&&if&(convertView&!=&null)&{&&view&=&convertV&&populate(view,&getItem(position));&&...&&}&else&{&&view&=&new&Xxx(...);&&...&&}&&return&&&}&
3.Bitmap对象不在使用时调用recycle()释放内存
有时我们会手工的操作Bitmap对象,如果一个Bitmap对象比较占内存,当它不在被使用的时候,可以调用Bitmap.recycle()方法回收此对象的像素所占用的内存,但这不是必须的,视情况而定。可以看一下代码中的注释:
&&&&&&&&&&&&&&&&&
4.试着使用关于application的context来替代和activity相关的context
这是一个很隐晦的内存泄漏的情况。有一种简单的方法来避免context相关的内存泄漏。最显著地一个是避免context逃出他自己的范围之外。使用Application
context。这个context的生存周期和你的应用的生存周期一样长,而不是取决于activity的生存周期。如果你想保持一个长期生存的对象,并且这个对象需要一个context,记得使用application对象。你可以通过调用
Context.getApplicationContext() or
Activity.getApplication()来获得。更多的请看这篇文章如何避免
Android内存泄漏。
5.注册没取消造成的内存泄漏
一些Android程序可能引用我们的Anroid程序的对象(比如注册机制)。即使我们的Android程序已经结束了,但是别的引用程序仍然还有对我们的Android程序的某个对象的引用,泄漏的内存依然不能被垃圾回收。调用registerReceiver后未调用unregisterReceiver。
比如:假设我们希望在锁屏界面(LockScreen)中,监听系统中的电话服务以获取一些信息(如信号强度等),则可以在LockScreen中定义一个
PhoneStateListener的对象,同时将它注册到TelephonyManager服务中。对于LockScreen对象,当需要显示锁屏界面的时候就会创建一个LockScreen对象,而当锁屏界面消失的时候LockScreen对象就会被释放掉。
但是如果在释放
LockScreen对象的时候忘记取消我们之前注册的PhoneStateListener对象,则会导致LockScreen无法被垃圾回收。如果不断的使锁屏界面显示和消失,则最终会由于大量的LockScreen对象没有办法被回收而引起OutOfMemory,使得system_process
进程挂掉。
虽然有些系统程序,它本身好像是可以自动取消注册的(当然不及时),但是我们还是应该在我们的程序中明确的取消注册,程序结束时应该把所有的注册都取消掉。
6.集合中对象没清理造成的内存泄漏
我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。
【编辑推荐】
【责任编辑: TEL:(010)】
关于&&的更多文章
本书是一本系统讲解Android应用开发安全的书籍。它首先介绍了And
随着云计算、物联网、大数据、移动互联网的大发展,你应该知道这些。
大家都知道iOS的发展之迅速,这对于开发者来说,无疑
越来越多的web设计师提出了移动优先的口号,而随着硬
北京时间日,苹果在加利福尼亚召开新品发
本书是由长期从事网络管理工作和网络工程人员培训工作的一线网管人员和教学人员精心编写,从现实的技术发展角度和实际应用的角度
Windows Phone专家
Android开发专家
51CTO旗下网站

我要回帖

更多关于 谈判时泄漏底线的后果 的文章

 

随机推荐