Android 开发中的内存泄漏

什么是内存泄漏

[](https://chinnsenn.com/2022/03...)定义

程序中动态分配的内存因为某种原因未释放或无法释放

通俗的讲,就是一个长生命周期对象 A 持有了一个短生命周期 B 对象的引用,导致 B 销毁时无法被 GC 回收,造成的内存浪费。

[](https://chinnsenn.com/2022/03...)危害

  • 用户对单次的内存泄漏并没有什么感知,但是当泄漏积累到内存都被消耗完,就会导致卡顿,甚至崩溃;
  • gc回收频繁 造成应用卡顿ANR:
  • 当内存不足的时候,gc会主动回收没用的内存.但是,内存回收也是需要时间的.- 内存回收和gc回收垃圾资源之间高频率交替的执行.就会产生内存抖动.
  • 很多数据就会污染内存堆,马上就会有许多GCs启动,由于这一额外的内存压力,也会产生突然增加的运算造成卡顿现象,
  • 任何线程的任何操作都会需要暂停,等待GC操作完成之后,其他操作才能够继续运行,所以垃圾回收运行的次数越少,对性能的影响就越少;

[](https://chinnsenn.com/2022/03...)如何分析内存泄漏

[](https://chinnsenn.com/2022/03...)1. 引用计数法

[](https://chinnsenn.com/2022/03...)原理

在堆中存储对象时,在对象头处维护一个counter计数器,如果一个对象增加了一个引用与之相连,则将counter++。如果一个引用关系失效则counter–。如果一个对象的counter变为0,则说明该对象已经被废弃,不处于存活状态。

[](https://chinnsenn.com/2022/03...)弊端

  • JDK 从1.2开始增加了多种引用方式:软引用、弱引用、虚引用,且在不同引用情况下程序应进行不同的操作。如果我们只采用一个引用计数法来计数无法准确的区分这么多种引用的情况。
  • 如果一个对象A持有对象B,而对象B也持有一个对象A,那发生了类似操作系统中死锁的循环持有,这种情况下A与B的counter恒大于1,会使得GC永远无法回收这两个对象。

[](https://chinnsenn.com/2022/03...)2.可达性分析算法

[](https://chinnsenn.com/2022/03...)原理

GC Roots 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的

[](https://chinnsenn.com/2022/03...)哪些对象可以作为 GC Roots

  • Java 虚拟机栈帧中的变量
  • 静态变量
  • 常量
  • JNI 引用对象

[](https://chinnsenn.com/2022/03...)3. Android 常见的内存泄漏场景

  • 单例
[](https://chinnsenn.com/2022/03...)起因

单例的生命周期贯穿整个 App 的生命周期,所以如果单例持有了某个短生命周期的对象引用(如 Activity、Fragment、View)等,将会引起内存泄漏

[](https://chinnsenn.com/2022/03...)解决方案

尽量不用传入短生命周期对象,不使用后及时置空,如需使用 Context 可传入 applicationContext

  • 静态变量
[](https://chinnsenn.com/2022/03...)起因

静态变量存储在方法区,它的生命周期从类加载开始,到整个进程结束。一旦静态变量初始化后,它所持有的引用只有等到进程结束才会释放。

[](https://chinnsenn.com/2022/03...)解决方案

  • 非静态内部类、匿名内部类
[](https://chinnsenn.com/2022/03...)起因

非静态内部类可以直接访问外部类的变量,通过 this$0 隐式持有外部类对象引用,如果内部类生命周期超过外部类,则可能造成内存泄漏。

  • 未反注册回调或监听器等
  • Timer 和 TimerTask 未及时关闭
  • 集合中对象引用未清理
  • 资源未关闭或释放(如 I/O)
  • 属性动画未及时 cancel
  • 关闭 WebView 后,未及时销毁

Webview 下面的 Callback 持有 Activity 引用,造成 Webview 内存无法释放,即使是调用了Webview.destory()等方法都无法解决问题(Android5.1之后)。最终的解决方案是:在销毁WebView之前需要先将WebView从父容器中移除,然后再销毁WebView。

以上是 Android 开发中的内存泄漏 的全部内容, 来源链接: utcz.com/z/267675.html

回到顶部