| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> 一切从Android的Handler讲起(八):Handler的内存泄露 -> 正文阅读 |
|
[移动开发]一切从Android的Handler讲起(八):Handler的内存泄露 |
作者:recommend-item-box type_blog clearfix |
一切从Android的Handler讲起(八):Handler的内存泄露??前面肥柴从浅入深,以Handler的基本工作机制为导入,进一步解析Handler机制的内部底层原理、Android触摸事件原理以及Android Framework层对消息机制的应用。这一篇章作为Handler的最后一个篇章,我们依旧从Handler入手,来谈谈内存泄漏的那些事。 一、内存泄露??内存泄漏是一个老生常谈的问题,也是面试容易问到的问题,那到底什么是内存泄漏呢? ??内存泄漏是指动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,直到程序结束。 ??java的优势之一就是内置了垃圾回收器GC,它帮助我们实现了自动化内存管理。但是GC再好,也有老马失前蹄的时候,它不能保证提供一个解决内存泄漏的万无一失的解决方案。而内存泄漏通俗的讲就是一部分内存空间明明已经使用了,却没有引用指向这部分空间,造成这片已经使用的空间无法处理的情况。 二、Handler的内存泄露??当我们尝试写一个Handler的匿名对象的时候,Android Studio会有如下报错,提示我们此写法存在内存泄漏。 ??那么为何Android Studio会有这种提示? ??答案很简单:因为匿名内部类默认会持有外部类Activity的引用,这样当Activity被销毁时,由于被匿名handler对象所持有而不能被释放,Activity所占用的内存就会泄露。 ??这是我们都知道的答案,那么问题又来了,为啥匿名内部类会持有外部类引用? ??这就得从匿名内部类的java编译后的.class文件说起,下面是肥柴把上面的匿名内部Handler类编译后的kotlin字节码代码。我们重点看注释1的地方,可以发现编译器为匿名内部类也单独生成了一份.class文件,而且其类名为Outer$1,并为其构造函数添加了一个参数,这个参数就是Outer类的实例,这就是为什么说匿名内部类默认会持有外部类的引用。
??同理,非静态内部类也是默认持有了外部类引用,而容易造成内存泄漏。 ??现在我们回到正题,因为Handler这个匿名内部类持有外部Activity的引用,导致Activity销毁时无法释放其内存,那为何Activity被引用了就无法释放Activity的内存呢? ??这里就涉及到了JVM的垃圾回收机制:如果GC Root到这个对象是引用链可达的话,那么此时就不能被GC垃圾回收掉此对象的内存。 ??而JVM内能充当GC Root对象的可以分为几种:1). 虚拟机栈/本地方法栈中JNI中的引用的对象。2). System Class Loader/Boot Class Loader加载的类对象。3). 激活状态的Thread 线程。4). 方法区中的常量引用的对象。5). 方法区里的类静态属性所引用的对象,等等。 ??肥柴利用内存泄漏工具分析Handler泄漏的真实引用链:Activity -> handler -> message -> queue -> UI线程。用最容易理解的一句话来回答为何会导致无法释放Activity的内存:由于激活状态的Thread线程是GC Root对象,此处对应了UI线程,那么由于UI线程一直处于激活状态,导致了这条引用链上的所有对象都不能被GC内存回收掉。 ??那根据这个理论,如果我们现在的handler关联的looper是子线程而非UI线程的话,因为随着子线程运行完毕,子线程的Looper和MessageQueue、Handler对象也随之消亡,这条引用链也就断裂了,Activity销毁后就可以被GC回收掉! 三、Handler内存泄漏的处理??既然我们知道了内存泄漏的真实原因,如何处理Handler引发的内存泄漏呢? ??最常见的答案便是:将Handler声明为静态内部类,同时为了能够使用到Activity的引用,可以使用弱引用处理Activity引用,避免GC无法释放Activity。 ??那有更简单更好的方法吗? ??其实是有的,这是肥柴也是很多读者最容易忽视的方法,同时也是最简单的方法:就是在Activity onDestroy()时调用handler.removeCallbacksAndMessages(null),这样就把Queue里所有的Message都remove掉了,之前说过Message被Message pool回收掉会reset,因此不会再引用Handler,这条引用链就断掉了。 ?- - - - - Handler的内存泄露完 - - - - - 结束??至此关于Handler的相关内容也就结束了,后续如有补充在继续扩展本篇章。 ??一、一切从Android的Handler讲起(一):Handler工作机制 ??二、一切从Android的Handler讲起(二):Message ??三、一切从Android的Handler讲起(三):Looper的唯一性——ThreadLocal ??四、一切从Android的Handler讲起(四):Looper消息获取 ??五、一切从Android的Handler讲起(五):延迟消息实现原理与消息机制的基本原理 ??六、一切从Android的Handler讲起(六):Android触摸事件基本原理 ??七、一切从Android的Handler讲起(七):Handler在Android系统框架层的应用 ??八、一切从Android的Handler讲起(八):Handler的内存泄露 ??篇章系列参考资料:https://www.zhihu.com/people/jing-shen-ling-xiu-68-79/posts ?- - - - - 一切从Android的Handler讲起篇章完 - - - - - |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 1:36:12- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |