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

所谓内存泄漏,就是本该被回收的对象,由于某些原因不能被回收,继续占用堆内存的这种状态,导致的结果也是显而易见的,会占用我们本可以使用的内存空间,当超出允许的内存时会引起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. MySql常用数据操作

    1.数据库操作: MySQL服务管理命令: 1.启动服务:sudo service mysql start 2.停止服务:sudo service mysql stop 3.重新启动服务:sudo s ...

  2. Oracle 数据库常用SQL语句(2)查询语句

    一.SQL基础查询 1.select语句 格式:select 字段 from 表名; 2.where 用于限制查询的结果. 3.查询条件 > < >= <= = != 4.与 ...

  3. day3-python 登录

    import datetime # 1. f = open('users') result = f.read() f.close() user_list = result.split() # user ...

  4. CentOS 系统下Gitlab搭建与基本配置 以及代码备份迁移过程

    GitLab 是一个开源的版本管理系统,提供了类似于 GitHub 的源代码浏览,管理缺陷和注释等功能,你可以将代码免费托管到 GitLab.com,而且不限项目数量和成员数.最吸引人的一点是,可以在 ...

  5. Laravel核心解读--Console内核

    Console内核 上一篇文章我们介绍了Laravel的HTTP内核,详细概述了网络请求从进入应用到应用处理完请求返回HTTP响应整个生命周期中HTTP内核是如何调动Laravel各个核心组件来完成任 ...

  6. Yii2.0学习--目录结构

    目录结构: 创建一个控制器: <?php /** * Created by Haima. * Author:Haima * QQ:228654416 * Date: 2018/8/23 * Ti ...

  7. Python之简单Socket编程

    Socket编程这块儿还是比较重要的,记录一下:实现服务器端和客户端通信(客户端发送系统指令,如ipconfig等,服务器端执行该指令,然后将指令返回结果给客户端再传过去,设置一次最多直接收1024字 ...

  8. BNU 3692 I18n 模拟

    题意: 在一篇文章中,单词可以缩写.例如单词Internationalization可以缩写为I18n,缩写的两端是原单词的首尾字母,中间的数字是被省略的字母的个数. 现在给你一篇缩写的文章,输出展开 ...

  9. 28、editText只输入英文字母和'-',用于授权码输入

    InputFilter filter = new InputFilter() { @Override public CharSequence filter(CharSequence source, i ...

  10. python常用方法总结

    1.os模块的路径拼接: import os now_path=os.path.abspath(__file__)#当前运行文件的路径 print(now_path) uppeer_path=os.p ...