Android内存泄露原因

来源:互联网 发布:修改数据库字段 编辑:程序博客网 时间:2024/05/16 11:39

讨论内存泄露需要先了解以下概念:

内存泄露

程序中所分配的堆内存不能被GC回收,其所占用的内存单元无法被释放出来,直到程序推出之前都不能被再使用。
出现内存泄露后会随着程序的运行导致内存越来越小,最终导致OOM(内存溢出),从而引起程序奔溃。

内存溢出

程序运行时所分配的内存超出了系统能够分配给该程序的内存,比如系统为一个程序分配了8M的内存,但是在该程序运行
的时候却分配了9M,那么这个时候就会报OOM异常,程序会奔溃退出。在程序运行中大量的内存泄露会导致内存溢出

内存区

  • 1.方法区
    所有线程共享该区域,存放所有的class和static变量和常量

  • 2.虚拟机栈(Stack)
    栈是最基本的数据结构,是一系列连续的内存单元,其特点是后进先出,该区域存放局部变量表,动态链接,方法出口等所需要的内存大小在编译时就已经完成分配,该区域不存放对象。该区域在方法执行结束后被分配的存储单元会被自动释放掉。

  • 3.堆(Heap)
    该区域所有线程共享,存放全局变量(包括基本类型和引用)和对象,其特点是:

    • 不连续
    • 空间大
    • 动态分配
      我们平时需要处理内存泄露的就是堆内存

引用类型

Java引用类型可以分为以下几种,在GC回收时会根据不同的引用类型做相应的处理。

  • 1、StrongReference,强引用:强引用就是普通的被实例化的对象引用,例如 Object obj = new Object()这样的引用,只有强引用还存在,就
    不会被回收。

  • 1、SoftReference,软引用:软引用用来指向一些不是必须的引用,在内存不足时先进行GC,如果内存还是不足,就会回收软引用,
    可以和ReferenceQueue结合使用,当被回收之后会把其放入ReferenceQueue中,可以通过这种方式来处理软引用被回收时的逻辑

  • 1、WeakReference,弱引用:弱引用也是用了指向不是必须的引用,但是在进行GC的时候若引用就会被回收。
    可以和ReferenceQueue结合使用,当被回收之后会把其放入ReferenceQueue中,可以通过这种方式来处理弱引用被回收时的逻辑

  • 1、PhatomReference, 虚引用:生命周期最短的引用类型,一般用来跟踪对象被垃圾回收的活动。虚引用必须和ReferenceQueue结合使用

开发时,为了防止内存溢出,处理一些占用内存比较大并且生命周期长的对象的时候,尽量使用软引用和弱引用。

GC回收

从GC Roots开始,从这个节点向下搜索,没有在GC搜索引用链上的引用就是不可用的,也就是从GC Root开始没有搜索到的,不可用的对象在GC时是可以被回收的。

这里写图片描述

如上图所示,从GC Roots开始搜索,发现obj8、obj9和obj10就是不可用的,虽然obj9和obj10之间有引用关系,但是不在GC Roots的引用链中,也是不可用的。

  • 1、虚拟机栈中引用的对象
  • 2、方法区中的静态引用对象
  • 3、方法区中的常量引用对象

Android引起内存泄露的原因

引起内存泄露的原因主要是一些对象实际上已经不再使用了,但是GC Root还有对它的引用,导致GC回收时该对象存在于GC Root的引用链上,导致无法回收。
Android常见的几种可能出现内存泄露的地方:

  • 1、static 的Activity,为了实现不同Activity之间的一些数据和方法的共享,定义一个静态的Activity(这样做的估计比较少)
  • 2、单例模式中定义Context全局变量,但是这个Context引用的是Activity,如有些项目需要编写一些单例模式的管理类或者工具类
  • 3、内部类,包括匿名内部类和普通内部类,内部类会隐似持有外部类的引用
  • 4、以内部类或者匿名内部类使用的Handler消息处理,这些内部类会持有外部类的实例,在消息没有处理完之前会一直持有引用,不会被销毁
  • 5、静态的View,为了实现一些动画或者其他一些功能定义的静态的View
  • 6、静态Bitmap或者Drawable,比如一些为了实现点击第一个界面中的图片启动另一个界面,在启动过程中需要对点击的图片做动画而定义的静态图片
  • 7、多线程,在使用多线程处理耗时操作时业务处理还没有完成,界面就推出了。
  • 8、观察者模式,在使用观察者模式实现一些功能的时候推出时没有清理相关引用,比如使用观察者实现业务处理监听回掉功能
  • 9、自定义View中自定义属性解析后没有调用recycle()方法进行回收。
  • 10、Bitmap使用后没有销毁
  • 11、无线轮播的动画,比如实现波浪动画,轮播动画等在onDestroy后没有回收。
  • 12、使用比较大并且比较多的图片实现帧动画(可能直接导致OOM)
  • 13、IO读写完成没有关闭
  • 14、使用Cursor操作数据库后没有关闭
原创粉丝点击