内存泄漏问题老生常谈,很常见也很难根治,今天我在这里总结一下内存泄漏的原因和解决方法:

所谓内存泄漏,就是本该被回收的对象,由于某些原因不能被回收,继续占用堆内存的这种状态,导致的结果也是显而易见的,会占用我们本可以使用的内存空间,当超出允许的内存时会引起OOM崩溃。

导致内存泄漏的原因大致分为:

  1. 集合类
  2. static修饰的成员变量
  3. 资源对象使用后未被关闭
  4. 非静态内部类/匿名类

1.集合类引起的内存泄漏:

当一个对象添加至集合中的时候,该对象会被集合引用到,当想要释放的时候不能释放,只有在集合被销毁的时候该对象才可以被释放

 // 通过 循环申请Object 对象 & 将申请的对象逐个放入到集合List
List<Object> objectList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Object o = new Object();
objectList.add(o);
o = null;
}
// 虽释放了集合元素引用的本身:o=null)
// 但集合List 仍然引用该对象,故垃圾回收器GC 依然不可回收该对象

解决方法:

因为是集合把对象引用了,那只需要吧集合释放掉集合对元素的引用也会被释放

//释放集合
objectList .clear();
objectList = null;

2.static修饰的成员变量:

因为被static修饰的成员变量生命周期 = 应用程序的生命周期,会在类被创建的时候加载到内存

static静态成员变量的生命周期>该类的生命周期导致该类没法释放

public class SecondActivity extends Activity{
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
SecondActivity.this.finish();
this.removeMessages(0);
}
}; private static Haha haha;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
haha = new Haha();
mHandler.sendEmptyMessageDelayed(0,2000);
} class Haha{ }
}

像上面这种情况SecondActivity是无法被释放掉的,只有把该静态成员变量置为null,这时就不会导致内存泄漏

protected void onDestroy() {
super.onDestroy();
if(haha!=null){
haha = null;
}
}

更常见的问题是在我们使用单例模式的时候:

public class LeakSingleInstance {

    private static LeakSingleInstance mInstance;
private Context mContext; private LeakSingleInstance(Context mContext){
this.mContext = mContext;
}
public static LeakSingleInstance getInstance(Context mContext) {
if(mInstance == null) {
mInstance = new LeakSingleInstance(mContext);
}
return mInstance;
}
}

这个在创建的时候AndroidStudio就提示有内存泄漏了,原因显而易见的,我们的单例模式的类是长期存在的,生命周期 = 应用生命周期,我们如果传入了上下文会导致该上下文长期被持有,不被释放,导致内存泄漏

解决方法可以使用:

mContext.getApplicationContext()

直接获取ApplicationContext的上下文使用,但是ApplicationContext使用是有局限性的,使用的时候要注意。

3.资源对象使用后未被关闭

对于资源的使用(如 广播BraodcastReceiver、文件流File、数据库游标Cursor、图片资源Bitmap等),若在Activity销毁时无及时关闭 / 注销这些资源,则这些资源将不会被回收,从而造成内存泄漏

// 对于 广播BraodcastReceiver:注销注册
unregisterReceiver() // 对于 文件流File:关闭流
InputStream / OutputStream.close() // 对于 数据库游标cursor:使用后关闭游标
cursor.close() // 对于 图片资源Bitmap:Android分配给图片的内存只有8M,若1个Bitmap对象占内存较多,当它不再被使用时,应调用recycle()回收此对象的像素所占用的内存;最后再赋为null
Bitmap.recycle();
Bitmap = null; // 对于动画(属性动画)
// 将动画设置成无限循环播放repeatCount = “infinite”后
// 在Activity退出时记得停止动画

还有非静态内部类和匿名类引起的泄漏,留在下篇再分析

by:Jungle张轶

Android内存泄漏总结的更多相关文章

  1. 【转】android 内存泄漏相关收藏博客。

    关于android内存泄漏的研究   博客建了几个月,都没有去写,一是因为当时换工作,然后又是新入职(你懂的,好好表现),比较忙:二是也因为自己没有写博客的习惯了.现在还算是比较稳定了,加上这个迭代基 ...

  2. 关于android内存泄漏的研究

    博客建了几个月,都没有去写,一是因为当时换工作,然后又是新入职(你懂的,好好表现),比较忙:二是也因为自己没有写博客的习惯了.现在还算是比较稳定了,加上这个迭代基本也快结束了,有点时间来写写博客.好了 ...

  3. Android内存泄漏的各种原因详解

    转自:http://mobile.51cto.com/abased-406286.htm 1.资源对象没关闭造成的内存泄漏 描述: 资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我 ...

  4. Android 内存泄漏优化汇总

    android内存泄漏优化摘要 博客分类: android android内存溢出OutOfMemoryError . android移动应用程序的内存分配一般是8凯瑟琳约,不正确地假定处理内存处理非 ...

  5. Android内存泄漏检测利器:LeakCanary

    Android内存泄漏检测利器:LeakCanary MAR 28TH, 2016 是什么? 一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具 为什么需要LeakCanary? ...

  6. Android 内存泄漏分析与解决方法

    在分析Android内存泄漏之前,先了解一下JAVA的一些知识 1. JAVA中的对象的创建 使用new指令生成对象时,堆内存将会为此开辟一份空间存放该对象 垃圾回收器回收非存活的对象,并释放对应的内 ...

  7. [Android]Android内存泄漏你所要知道的一切(翻译)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/7235616.html Android内存泄漏你所要知道的一切 ...

  8. LeakCanary 来检查 Android 内存泄漏

    LeakCanary 来检查 Android 内存泄漏

  9. Android内存泄漏的检测流程、捕捉以及分析

    https://blog.csdn.net/qq_20280683/article/details/77964208 Android内存泄漏的检测流程.捕捉以及分析 简述: 一个APP的性能,重度关乎 ...

  10. Android内存泄漏原因

    这段时间调试APP的时候,发现程序在加载了过多的bitmap后会崩溃.查看了日志,原来是发生了内存溢出(OOM).第一次遇到这样的问题,那就慢慢排查吧. 内存优化可以参考胡凯大神的博客Android内 ...

随机推荐

  1. LeetCode之Weekly Contest 93

    第一题:二进制间距 问题: 给定一个正整数 N,找到并返回 N 的二进制表示中两个连续的 1 之间的最长距离. 如果没有两个连续的 1,返回 0 . 示例 1: 输入:22 输出:2 解释: 22 的 ...

  2. paper:synthesizable finit state machine design techniques using the new systemverilog 3.0 enhancements之enhanced coding styles

    1.ANSI style 的代码比较紧凑. 下面规范推荐,比较好. 下面是带有parameter的module header的完整规范 一般1bit ,大家都是wire signal1 = gen_s ...

  3. Python基础(三)—— print()格式化输出变量

    先举一个简单的例子说明: name = 'Jack' answer = input('你好,%s '%(name) + '你认识 Sean 不, 输入 yes or no\n') print('Sea ...

  4. nw335 debian sid x86-64 -- 1 需求介绍

    自己的台式机上面有有线网卡,路由器在客厅,托一条长长的线,关门也不方便.没有选择PCI无线网卡,没有选择nano类型的迷你网卡.买了nw335,带一条5DB天线,信号应该会好点.于是,开始了在debi ...

  5. Page-Object思想

    为什么要使用page-object 集中管理元素对象 集中管理一个page内的公共方法 后期维护方便 集中管理元素对象 实现方法: 调用方法: WebElement element = dri ...

  6. Monkeyrunner 简介及其环境搭建

    Monkeyrunner是通过坐标.控件ID和控件上的文字操作应用的界面元素,其测试用例是用python写的,这样就弥补了monkey只有简单命令无法执行复杂用例的缺陷.Monkeyrunner采用的 ...

  7. Apache下error.log文件太大的处理方法

    清除error.log.access.log并限制Apache日志文件大小的方法,在网上搜了下相应的资料,并按照如下步骤做了一遍,网站恢复正常   清除error.log.access.log并限制A ...

  8. ranorex前一步的操作结果后一步如何调用

     if (!TestSuite.Current.Parameters.ContainsKey("Password"))TestSuite.Current.Parameters.Ad ...

  9. pl/sql的控制结构,分支、循环、控制

    一.pl/sql的进阶--控制结构在任何计算机语言(c,java,pascal)都有各种控制语句(条件语句,循环结构,顺序控制结构...),在pl/sql中也存在这样的控制结构.在本部分学习完成后,希 ...

  10. DS-博客作业06--图

    DS-博客作业06--图 1.本周学习总结(0--2分) 1.思维导图 2.谈谈你对图结构的认识及学习体会. 本章的图,因为和上一章的树上的比较紧凑,所以在考前一个星期也有看书背代码,也有理解代码和思 ...