返回顶部
首页 > 资讯 > 移动开发 >Android内存泄漏导致原因深入探究
  • 525
分享到

Android内存泄漏导致原因深入探究

Android内存泄漏原因Android内存泄漏几种情况 2023-02-17 18:02:54 525人浏览 安东尼
摘要

目录什么是内存泄露哪些操作会造成内存泄漏常见内存泄露问题1.资源性对象未关闭2.注册对象未注销3.非静态内部类的静态实例4.单例模式引起的内存泄露5.Handler临时性内存泄露6.

什么是内存泄露

什么是内存泄露,通俗的来说就是堆中的一些对象已经不会再被使用了,但垃圾收集器却无法将它们从内存中清除。

内存泄漏很严重的问题,因为它会阻塞内存资源并随着时间的推移降低系统性能。如果不进行有效的处理,最终的结果将会使应用程序耗尽内存资源,无法正常服务,导致程序崩溃,抛出java.lang.OutOfMemoryError异常。

堆内存中通常有两种类型的对象:被引用的对象和未被引用的对象。被引用的对象是应用程序中仍然具有活跃的引用,而未被引用的对象则没有任何活跃的引用。

垃圾收集器会回收那些未被引用的对象,但不会回收那些还在被引用的对象。这也是内存泄露发生的源头。

哪些操作会造成内存泄漏

下面我们介绍几种常见的造成内存泄露的情况

1、意外声明全局变量是最常见也最容易修复的内存泄漏问题,比如:

function fn() {
    name = '张三';
}

解释器在解释上面的函数时,会把name当做全局变量,即window.name = ‘张三’。只要window对象没有被清理,那么name属性和属性值将一直存在,造成内存泄露。

解决方法:

(1)只要在变量声明前面加上var、let或const关键字即可,这样变量就会在函数执行完毕后离开作用域。

(2)使用this关键字

function fn() {
    this.name = '张三';
}

(3)可以在 javascript 文件开头添加 “use strict”,使用严格模式。这样在严格模式下解析 JavaScript 可以防止意外的全局变量

(4)在使用完之后,对其赋值为null或者重新分配

2、 定时器导致的泄露

let name = '张三';
setInterval(() => {
    console.log(name);
}, 100);

上面的代码中,只要定时器一直运行,回调函数中引用的name就会一直占用内存。

3、闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环),下面我们看一个JavaScript闭包导致的内训泄露例子

let fun = function() {
    let name = '张三';
    return function() {
        return name;
    };
};

调用fun()会导致分配给name的内存被泄漏。以上代码执行后创建了一个内部闭包,只要返回的函数存在就不能清理name,因为闭包一直在引用着它。

常见内存泄露问题

1.资源性对象未关闭

资源性对象(如Cursor、File等一些Closeable对象),它们往往使用了缓冲区,缓冲区不仅在JVM内,JVM之外也有。如果仅仅把变量设置为null,而不关闭它们,缓冲区得不到释放,往往造成内存泄露。

解决方案:一般在finally中关闭资源型对象,而后设置对象为null

2.注册对象未注销

订阅者模式中,如果注册对象不再使用时,未及时注销,会导致订阅者列表中维持这对象的引用,阻止垃圾回收,导致内存泄露。常见场景:动态注册BroadcastReceiver,注册PhoneStateListener,注册EventBus等等,

还有自定义使用订阅者模式的情形。

解决方案:一般在onDestroy()中进行解注册

3.非静态内部类的静态实例

非静态内部类持有外部类实例的引用,若非静态内部类的实例是静态的,便拥有app存活期整个生命周期,长期持有外部类的引用,阻止外部类实例被回收。

使用内部类的情况十分常见,尤其是匿名内部类:一些接口的匿名实现类,都是内部类。

解决方案:(1)改为静态内部类,不再持有外部类实例的引用 (2)避免申明非静态内部类的静态实例 (3)将内部类抽取出来封装成一个单例,如果需要Context,没有特殊要求就使用Application Context;如果需要Activity Context,则使用完毕置空,或者使用弱引用

4.单例模式引起的内存泄露

由于单例模式的静态特性,使得它的生命周期和我们的应用一样长,如果让单例无限制的持有Activity的强引用就会导致内存泄漏

解决方案:使用Activity的弱引用,或者没特殊需求时使用Application Context

5.Handler临时性内存泄露

非静态Handler持有Activity或Service的引用,Message中的target指向Handler实例,所以当Message在MessageQueue中排队,长时间未得到处理时,Activity边不会被回收,导致临时性内存泄露。

解决方案:(1)使用静态Handler内部类,然后对Handler持有的对象(Activity或Service)使用弱引用 (2)在onDestroy()中移除消息队列中的消息 mHandler.removeCallbacksAndMessages(null)

类似的:AsyncTask内部也是Handler机制,也存在同样的临时性内存泄露风险

6.容器中对象未及时清理导致内存泄露

容器类一般拥有较长的生命周期,若内部不再使用的对象不及时清理,内部对象边一直被容器类引用。上述2中的订阅者列表也属于容器类这中情况。另外常见的容器类还有线程池、对象池、图片缓存池等。线程池中的线程若存在ThreadLocal对象,因为线程对象一直被循环使用,ThreadLocal对象便会一直被引用,要注意对value对象的置空释放。

7.静态View导致内存泄露

有时,当一个Activity经常启动,但是对应的View读取非常耗时,我们可以通过静态View变量来保持对该Activity的rootView引用。这样就可以不用每次启动Activity都去读取并渲染View了。这确实是一个提高Activity启动速度的好方法!但是要注意,一旦View attach到我们的Window上,就会持有一个Context(即Activity)的引用。而我们的View有事一个静态变量,所以导致Activity不被回收。 解决办法:在使用静态View时,需要确保在资源回收时,将静态View detach掉。

8.属性动画未及时关闭导致内存泄露

在使用ValueAnimator或者ObjectAnimator时,如果没有及时做cancel取消动画,就可能造成内存泄露。 因为在cancel方法里,最后调用了endAnimation(); ,在endAnimation里,有个AnimationHandler的单例,会持有属性动画对象的引用

解决办法:在在onDestory时,调用动画的cancel方法

9.WebView内存泄露

目前Android中WebView的实现存在很大的兼容性问题,Google支持各个ROM厂商自行定制自己的WebView实现,各个ROM间差异较大,且大多都存在内存泄露问题。除了调用其内部的clearCache()、clearHistory()、removeAllViews()、freeMemory()、destroy()和置null以外,一般比较粗暴有效的解决方法是:将包含WebView的Activity放在一个单独的进程中,不需要时将进程销毁,从而释放所有所占内存。

10.其他的系统控件以及自定义View

在 Android Lollipop 之前使用 AlertDialog 可能会导致内存泄漏

view中有线程或者动画 要及时停止。这是为了防止内存泄漏,可以在onDetachedFromWindow方法中结束,这个方法回调的时机是 当View的Activity退出或者当前View被移除的时候 会调用 这时候是结束动画或者线程的好时机 另外还有一个对应的方法 onAttachedToWindow 这个方法调用的时机是在包含View的Activity启动时 回调 回调在onDraw方法之前

11.其他常见的引起内存泄漏原因

  • (1)构造Adapter时,没有使用缓存的 contentView
  • (2)Bitmap在不使用的时候没有使用recycle()释放内存
  • (3)警惕线程未终止造成的内存泄露;譬如在Activity中关联了一个生命周期超过Activity的Thread,在退出Activity时切记结束线程。一个典型的例子就是HandlerThread的run方法是一个死循环,它不会自己结束,线程的生命周期超过了Activity生命周期,我们必须手动在Activity的销毁方法中调用thread.getLooper().quit();才不会泄露
  • (4)避免代码设计模式的错误造成内存泄露;譬如循环引用,A持有B,B持有C,C持有A,这样的设计谁都得不到释放

文末

理解内存泄漏的危害,我们举个简单的例子。有一个宾馆,有100间房间,顾客每次都是在前台进行登记,然后拿到房间钥匙。如果有些顾客不需要该房间了,也不归还钥匙,久而久之,前台处可用房间越来越少,收入也越来越少,濒临倒闭。当程序申请了内存,而不进行归还,久而久之,可用内存越来越少,OS就会进行自我保护,杀掉该进程,这就是我们常说的OOM(out of memory)。

到此这篇关于Android内存泄漏导致原因深入探究的文章就介绍到这了,更多相关Android内存泄漏内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Android内存泄漏导致原因深入探究

本文链接: https://lsjlt.com/news/196627.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android内存泄漏导致原因深入探究
    目录什么是内存泄露哪些操作会造成内存泄漏常见内存泄露问题1.资源性对象未关闭2.注册对象未注销3.非静态内部类的静态实例4.单例模式引起的内存泄露5.Handler临时性内存泄露6....
    99+
    2023-02-17
    Android内存泄漏原因 Android内存泄漏几种情况
  • ThreadLocal导致JVM内存泄漏原因探究
    目录为什么要使用ThreadLocal使用ThreadLocal具体实现引发内存泄漏的原因为什么要使用ThreadLocal 在一整个业务逻辑流程中,为了在不同的地方或者不同的方法中...
    99+
    2023-05-16
    JVM内存泄漏 JVM ThreadLocal内存泄漏
  • Android内存泄漏导致的原因有哪些
    这篇文章主要介绍“Android内存泄漏导致的原因有哪些”,在日常操作中,相信很多人在Android内存泄漏导致的原因有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android内存泄漏导致的原因有哪些...
    99+
    2023-07-05
  • Android内存泄漏的原因有哪些
    Android内存泄漏的原因有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在Android开发中,最容易引发的内存泄漏问题的是Context。比如Activity的Con...
    99+
    2023-06-17
  • OpenCL clCreateContextFromType函数导致内存泄漏
    内存泄漏是一种资源管理问题,可能会导致程序运行时消耗大量的内存而无法释放。在OpenCL中,clCreateContextFromT...
    99+
    2023-09-26
    内存泄漏
  • 内存泄露导致Android 中setVisibility() 失效原理
    目录一、前情概要二、摸索过程1、代码执行了吗?2、视图不显示的直接原因是什么?3、操作的视图是同一个吗?三、解决方案一、前情概要 目前,我在开发的一个 Android 项目需要各个功...
    99+
    2024-04-02
  • javascript内存泄漏有哪些原因
    本篇内容介绍了“javascript内存泄漏有哪些原因”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2024-04-02
  • JavaScript中的内存泄漏的原因
    目录前言内存泄漏的场景全局变量闭包DOM元素引用总结前言 JavaScript的内存泄漏指的是一些不再需要的对象仍然占用着内存,导致内存使用量持续增加,甚至造成浏览器崩溃或性能下降。...
    99+
    2023-05-18
    JavaScript 内存泄漏
  • 深入探究HashMap二次Hash原因
    目录1. 前言2. 哈希码的作用3. 二次Hash4. 为啥右移16位5. 总结1. 前言 HashMap对于Java程序员来说一定不陌生,除了平时开发会经常使用外,它也是面试官非常...
    99+
    2023-01-04
    HashMap二次Hash Java HashMap Hash
  • 深入探究 C++ 编程中的资源泄漏问题
    目录 1、GDI对象泄漏 1.1、何为GDI资源泄漏? 1.2、使用GDIView工具排查GDI对象泄漏 来源地址:https://blog.csdn.net/chenlycly/article/details/133631728...
    99+
    2023-10-24
    C++程序 资源泄露 GDI对象泄漏 句柄泄露 内存泄漏 GDIView Windbg
  • python内存泄漏的原因有哪些
    Python内存泄漏的原因有以下几个:1. 循环引用:当两个或多个对象相互引用时,如果没有妥善地处理,可能会导致内存泄漏。垃圾回收器...
    99+
    2023-09-15
    python
  • golang内存泄漏的原因是什么
    这篇“golang内存泄漏的原因是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“golang内存泄漏的原因是什么”文章吧...
    99+
    2023-07-04
  • GoLang内存泄漏原因排查详解
    目录背景临时性内存泄漏通道理解背景 Go 语言中有对应的Go 内存回收机制,在Go采用 并发三色标记清除  算法, 但是由于实际的过程中 发现会有一些内存泄漏的常见,内存泄...
    99+
    2022-12-15
    GoLang内存泄漏 Go内存泄漏
  • Java中什么情况会导致内存泄漏
    这篇文章主要讲解了“Java中什么情况会导致内存泄漏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中什么情况会导致内存泄漏”吧!概念内存泄露:指程序中动态分配内存给一些临时对象,但对...
    99+
    2023-06-16
  • android内存泄露:4、Toast的错误使用导致内存泄露
    目录 一、前言 二、Toast的错误使用导致内存泄露 1、新建一个 Module,写主界面 MainActivity,布局 activity_main 2、写业务逻辑 3、效果...
    99+
    2022-06-06
    toast Android
  • android内存泄漏的原因及解决方法是什么
    Android内存泄漏的原因可能有以下几个:1. 长生命周期的对象持有短生命周期的引用:当一个长生命周期的对象持有了一个短生命周期对...
    99+
    2023-08-08
    android
  • java内存泄漏和内存溢出的原因是什么
    Java内存泄漏和内存溢出的原因如下:1. 内存泄漏:内存泄漏指的是在程序运行过程中,无用的对象仍然被保持在内存中,导致内存占用不断...
    99+
    2023-08-26
    java
  • golang容易导致内存泄漏的6种情况汇总
    目录1. 定时器使用不当1.1 time.After()的使用1.2 time.NewTicker资源未及时释放2. select阻塞2.1 导致goroutine阻塞的情况2.2 ...
    99+
    2023-01-09
    golang内存泄漏例子 go 内存泄漏 golang内存泄漏场景
  • JavaScript中出现内存泄漏的原因是什么
    本篇文章给大家分享的是有关JavaScript中出现内存泄漏的原因是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。泄露方式在接下来的内容中...
    99+
    2024-04-02
  • Node.js中出现内存泄漏的原因有哪些
    本篇文章给大家分享的是有关Node.js中出现内存泄漏的原因有哪些,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。内存泄漏(Memory  Leak)指由于疏忽或错误造...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作