一:什么是内存泄露
内存泄露是指:内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。

二:常见的内存泄露造成的原因
1、单例造成的内存泄漏
由于单例的静态特性使得其生命周期和应用的生命周期一样长,如果一个对象已经不再需要使用了,而单例对象还持有该对象的引用,就会使得该对象不能被正常回收,从而导致了内存泄漏。
示例:防止单例导致内存泄漏的实例

// 使用了单例模式
public class AppManager {private static AppManager instance;private Context context;private AppManager(Context context) {this.context = context;}public static AppManager getInstance(Context context) {if (instance != null) {instance = new AppManager(context);}return instance;}
}

2、非静态内部类创建静态实例造成的内存泄漏
例如,有时候我们可能会在启动频繁的Activity中,为了避免重复创建相同的数据资源,可能会出现如下写法:

  public class MainActivity extends AppCompatActivity {private static TestResource mResource = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if(mResource == null){mResource = new TestResource();}//...}class TestResource {//...}
}

3、Handler造成的内存泄漏
示例:创建匿名内部类的静态对象

public class MainActivity extends AppCompatActivity {private final Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {// ...}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);new Thread(new Runnable() {@Overridepublic void run() {// ...handler.sendEmptyMessage(0x123);}});}
}

1、从Android的角度
当Android应用程序启动时,该应用程序的主线程会自动创建一个Looper对象和与之关联的MessageQueue。当主线程中实例化一个Handler对象后,它就会自动与主线程Looper的MessageQueue关联起来。所有发送到MessageQueue的Messag都会持有Handler的引用,所以Looper会据此回调Handle的handleMessage()方法来处理消息。只要MessageQueue中有未处理的Message,Looper就会不断的从中取出并交给Handler处理。另外,主线程的Looper对象会伴随该应用程序的整个生命周期。
2、 Java角度
在Java中,非静态内部类和匿名类内部类都会潜在持有它们所属的外部类的引用,但是静态内部类却不会。
对上述的示例进行分析,当MainActivity结束时,未处理的消息持有handler的引用,而handler又持有它所属的外部类也就是MainActivity的引用。这条引用关系会一直保持直到消息得到处理,这样阻止了MainActivity被垃圾回收器回收,从而造成了内存泄漏。
解决方法:将Handler类独立出来或者使用静态内部类,这样便可以避免内存泄漏。

4、线程造成的内存泄漏
示例:AsyncTask和Runnable

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);new Thread(new MyRunnable()).start();new MyAsyncTask(this).execute();}class MyAsyncTask extends AsyncTask<Void, Void, Void> {// ...public MyAsyncTask(Context context) {// ...}@Overrideprotected Void doInBackground(Void... params) {// ...return null;}@Overrideprotected void onPostExecute(Void aVoid) {// ...}}class MyRunnable implements Runnable {@Overridepublic void run() {// ...}}
}

AsyncTask和Runnable都使用了匿名内部类,那么它们将持有其所在Activity的隐式引用。如果任务在Activity销毁之前还未完成,那么将导致Activity的内存资源无法被回收,从而造成内存泄漏。
解决方法:将AsyncTask和Runnable类独立出来或者使用静态内部类,这样便可以避免内存泄漏。

5、资源未关闭造成的内存泄漏
对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,从而造成内存泄漏。
1)比如在Activity中register了一个BraodcastReceiver,但在Activity结束后没有unregister该BraodcastReceiver。
2)资源性对象比如Cursor,Stream、File文件等往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。它们的缓冲不仅存在于 java虚拟机内,还存在于java虚拟机外。如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄漏。
3)对于资源性对象在不使用的时候,应该调用它的close()函数将其关闭掉,然后再设置为null。在我们的程序退出时一定要确保我们的资源性对象已经关闭。
4)Bitmap对象不在使用时调用recycle()释放内存。2.3以后的bitmap应该是不需要手动recycle了,内存已经在java层了。

6、使用ListView时造成的内存泄漏
初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的View对象,同时ListView会将这些View对象缓存起来。当向上滚动ListView时,原先位于最上面的Item的View对象会被回收,然后被用来构造新出现在下面的Item。这个构造过程就是由getView()方法完成的,getView()的第二个形参convertView就是被缓存起来的Item的View对象(初始化时缓存中没有View对象则convertView是null)。
构造Adapter时,没有使用缓存的convertView。
解决方法:在构造Adapter时,使用缓存的convertView。

7、集合容器中的内存泄露
我们通常把一些对象的引用加入到了集合容器(比如ArrayList)中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。
解决方法:在退出程序之前,将集合里的东西clear,然后置为null,再退出程序。

8、WebView造成的泄露
当我们不要使用WebView对象时,应该调用它的destory()函数来销毁它,并释放其占用的内存,否则其长期占用的内存也不能被回收,从而造成内存泄露。
解决方法:为WebView另外开启一个进程,通过AIDL与主线程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。

三:如何避免内存泄漏?

1、平常养成良好的代码书写习惯,该销毁的对象要销毁比如destory啊 广播啊 ,涉及到要用到content上下文的优先考虑全局上线文对象。

什么是内存泄漏,常见引起引起内存泄漏的原因,及解决办法相关推荐

  1. 常见过拟合、欠拟合原因及解决办法

    引言 在机器学习中,我们将模型在训练集上的误差称之为训练误差,又称之为经验误差,在新的数据集(比如测试集)上的误差称之为泛化误差,泛化误差也可以说是模型在总体样本上的误差.对于一个好的模型应该是经验误 ...

  2. 内存泄漏的原因及解决办法_探索内存碎片化 - 第288篇

    相关历史文章(阅读本文之前,您可能需要先看下之前的系列 ) 色谈Java序列化:女孩子慎入 - 第280篇 烦不烦,别再问我时间复杂度了:这次不色,女孩子进来吧 - 第281篇 双向链表,比西天还远? ...

  3. java 内存 溢出_java内存溢出的几种原因和解决办法是什么?

    java内存溢出的几种原因和解决办法是什么? java内存溢出的几种原因和解决办法是: 第一类内存溢出,也是大家认为最多,第一反应认为是的内存溢出,就是堆栈溢出: 那什么样的情况就是堆栈溢出呢?当你看 ...

  4. linux下hg无法运行_Linux 无法启动常见的几种原因及解决办法

    导致 Linux 无法启动的原因有很多,下面良许小编就将常见的几种原因及解决办法进行详述,希望对大家有所帮助. 文件系统配置不当,如 /etc/inittab文件./etc/fstab 文件等配置错误 ...

  5. 杂散干扰解决办法_实用干货——6种常见杂散问题的成因分析及解决办法

    原标题:实用干货--6种常见杂散问题的成因分析及解决办法 虽然目前的高分辨率SAR ADC和Σ-Δ ADC可提供高分辨率和低噪声,但可能难以实现数据手册上的额定SNR性能.而要达到最佳SFDR,也就是 ...

  6. PPTP连接时常见拨号错误提示原因及解决办法

    相信大家在连接PPTP的时候,总会出现这样那样的错误代码,很令人头疼,下面我为大家整理了一些常见的错误代码供参考: ×××错误619解决办法 详解:私设IP或路由器不支持ppTp pass throu ...

  7. windows常见的加载错误的3个解决办法

    windows常见的加载错误的3个解决办法 作者:系统达人 来源:http://www.dnxp.net 当在系统中频繁安装和卸载一些应用程序,或者频繁对系统进行杀毒操作的话,系统在日后的启动过程中可 ...

  8. 苹果手机发热发烫怎么办?常见原因及解决办法

    很多小伙伴都喜欢使用苹果手机,有时候正在玩着苹果手机的时候,发现自己的苹果手机温度很高,很烫手,这是怎么一回事呢?苹果手机发热发烫怎么办?别担心,下面跟着小编一起来看看苹果手机发热发烫常见的原因和解决 ...

  9. PPTP连接时常见错误提示原因及解决办法

    相信大家在连接PPTP的时候,总会出现这样那样的错误代码,很令人头疼,下面我为大家整理了一些常见的错误代码供参考: ×××错误619解决办法 详解:私设IP或路由器不支持ppTp pass throu ...

最新文章

  1. 每天一道LeetCode-----只可能有'.'和'*'的字符串正则匹配
  2. jmeter 获取全部响应_Jmeter获取响应结果中参数出现的次数
  3. 巧用 PHP 数组函数 1
  4. JAVA高并发服务器工作笔记0001---Java中InetAddress与InetSocketAddress的基本用法
  5. 面试稳了!网易资深工程师详解运维面经!
  6. android开关控件Switch和ToggleButton
  7. python没有报错但是没结果_python爬取豆瓣top250的电影的信息,没有报错哦,但是没有结果...
  8. 操作系统的不确定性是指_读文||不确定性原理—人工智能的哲学基础
  9. 超强合集:OCR 文本检测干货汇总(含论文、源码、demo 等资源)
  10. centos7 播放网页flash视频
  11. 前馈神经网络(FNN)
  12. 第三次郑州.NET俱乐部活动总结
  13. 用matlab做矩阵变换(理解+实践);假设随机发给某班所有同学任意数字,生成10*5的矩阵
  14. MySQL中的聚簇索引、非聚簇索引、联合索引和唯一索引
  15. 【GStreamer 】3-6 gstreamer jpegenc 、jpegdec 插件说明
  16. 芝诺数解|「十五」考研路漫漫,行则将至——重庆考研分析报告
  17. 加推携手京东开普勒打造超级IP名片,让人人都能轻松创业开店!
  18. MTK6572关于相机默认像素问题
  19. K-均值(means聚类)算法
  20. kaggle简单实战——房价预测(xgboost实现)

热门文章

  1. 带你了解软件工程中的类与类的关系
  2. 牛客练习赛20 托米历险记
  3. ArcGIS二次开发基础教程:开发环境配置教程(ArcEngine10.4+VS2019)
  4. 头腾隐私大战的背后,转折中的互联网世界
  5. 【数字音频】采样率、声道与采样深度
  6. python写的游戏有哪些_python做的游戏有哪些
  7. linux终端执行二进制文件命令,关于Linux常用的二进制文件分析方法
  8. 鼠标单击改变按钮颜色_如何在iPad上用鼠标单击“主页”按钮
  9. 目标检测误检与负样本问题
  10. Sqlserver 双机热备份_从数据库发布(主从备份)