Android常见内存泄漏场景总结
一、非静态内部类造成的内存泄漏
造成原因:非静态内部类默认会持有外部类的引用,如果内部类的生命周期超过了外部类就会造成内存泄漏。
场景:当Activity销毁后,由于内部类中存在异步耗时任务还在执行,导致Activity实例一直被内部类持有无法被回收,造成内存泄漏
例如:
//TestActivity
button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {new Thread(new Runnable() {@Overridepublic void run() {try {//模拟耗时Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}).start();}});
此时点击返回键关闭当前Activity,页面正常回退,但匿名内部类中还有耗时任务执行,如果耗时任务执行完之后要刷新页面还会造成异常导致app闪退。
解决办法:不使用匿名内部类,并且使用static关键字修饰内部类(static修饰的内部类不持有外部类的引用,也自然不会造成上面的内存泄漏),如果内部类中需要使用外部类的资源,可以使用弱引用的方式持有外部类。
优化后的代码如下:
button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {new Thread(new MyRunnable()).start();}});static class MyRunnable implements Runnable{@Overridepublic void run() {try {//模拟耗时Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
二、静态成员变量造成的内存泄漏
造成原因:静态成员变量的生命周期 = 应用程序的生命周期,如果该静态成员应用的变量生命周期 < 改静态变量则会造成内存泄漏
场景:静态成员变量持有了一个耗费资源过多的实例(Activity,Fragment)
例如:
public class Person {private static Activity mActivity;Person(Activity activity){mActivity = activity;}
}
此时点击返回键关闭当前Activity,但Person类中的mActivity静态变量持有当前Activity的引用,导致改Activity对象本该被回收而没被回收,导致内存泄漏
解决办法:
- 尽量避免
Static成员变量引用资源耗费过多的实例(如Context) - 如果必须使用Context,可以使用Application的Context
- 使用弱引用代替强引用持有
三、单例模式造成的内存泄漏
造成原因:单例模式由于其具有静态特性,导致其生命周期 = 应用程序生命周期,如果单例中持有别的类的实例,就会造成内存泄漏
场景:单例模式中持有一个耗费资源过多的实例(Context)
例如:
public class SingleInstance{private static SingleInstance instance;private Context mContext;private SingleInstance(Context context) {this.mContext = context; // 传递的是Activity的context}public SingleInstance getInstance(Context context) {if (instance == null) {instance = new SingleInstance(context);}return instance;}
}
此时由于单例中持有传入的Activity实例,倒是该Activity关闭时,资源得不到回收,从而造成内存泄漏
解决办法:
使用Application的Context代替Activity的Contex
四、Handler造成的内存泄漏
造成原因:当使用非静态内部类(包含匿名内部类)创建Handler时,Handler会持有外部类的对象,如果Handler中还有消息没执行完,此时创建Handler的Activity关闭就会造成内存泄漏。通常由于子线程持有handler的引用(因为要发消息给handler来更新界面),handler又持有activity的引用,从而导致activity不能正常被回收,造成内存泄漏
场景:Activity中通过一个子线程异步请求网络数据,请求成功后更新当前页面。
例如:
//MainActivity.javaprivate Handler mHandler = new Handler(Looper.getMainLooper()){@Overridepublic void handleMessage(Message msg) {//更新页面}};//成功获取到网络数据更新页面private void handleData(String data){Message message = Message.obtain();message.obj = data;mHandler.sendMessage(message);
}
解决办法:
1、静态内部类+弱引用
static class MyHandler extends Handler {WeakReference<Activity > mReference;MyHandler(Activity activity) {mReference= new WeakReference<Activity>(activity);}@Overridepublic void handleMessage(Message msg) {final Activity activity = mReference.get();if (activity != null) {//更新页面}}
}
2、activity销毁时,及时清理消息
@Override
protected void onDestroy() {super.onDestroy();if (mHandler != null) {mHandler.removeCallbacksAndMessages(null);}
}
五、多线程造成的内存泄漏
造成原因:上面一和四其实也是多线程造成内存泄漏的场景,主要是子线程中持有外部类(例如Activity)的引用,让后子线程的生命周期又和Activity不同步,从而造成activity被销毁时子线程中的任务还在执行,从而导致activity的资源迟迟得不到回收造成内存泄漏。
六、集合类造成的内存泄漏
造成原因:当我们把一些对象的引用加入到集合对象(例如常用的ArrayList),当我们不需要改对象时,没有从集合中清理掉改对象的引用,这样集合就会越来越大,如果集合时static的那问题就更严重了。
场景:学生管理系统中需要统计学生信息,使用一个集合存储学生信息,信息统计完成,把信息存入数据库后就不需要学生对象信息了,但是没及时清理掉集合,导致学生对象得不到回收,造成内存泄漏
例如:
// 通过 循环申请Person 对象并放入集合
List<Person> personList = new ArrayList<>();for (int i = 0; i < 10; i++) {Person p = new Person();personList.add(p);
// 虽释放了集合元素引用的本身:p=null
// 但集合List仍然吃药后该对象引用,所以依然不可回收该对象p = null;
}
解决办法:在不使用改集合时,清理集合并把集合置为空
// 释放personList
personList.clear();
personList=null;
七、WebView造成的内存泄漏
造成原因:WebView中可能会进行大量的网络请求,加载大量的资源,从而使得内存占用过高,当我们推出承载Webview的Activity时,没有正确的释放WebView中的资源,导致内存泄漏。
例如:新闻列表页面使用WebView加载一个h5页面,此时会进行大量网络请求加载新闻图片内容,当我们回退该页面时,加载的资源没正确释放导致内存泄漏
解决方案:不使用xml定义webview,通过代码的形式,传入Application的Context然后在承载webview的页面销毁时,释放webview的资源
//代码初始化Webview
mWebView=new WebView(getApplicationContext());
LinearLayout linearLayout = findViewById(R.id.webview);
linearLayout.addView(mWebView);@Override
protected void onDestroy() {if( mWebView!=null) {// 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再// destory()ViewParent parent = mWebView.getParent();if (parent != null) {((ViewGroup) parent).removeView(mWebView);}mWebView.stopLoading();// 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错mWebView.getSettings().setJavaScriptEnabled(false);mWebView.clearHistory();mWebView.clearView();mWebView.removeAllViews();mWebView.destroy();}super.on Destroy();
}
八、资源未释放造成的内存泄漏
造成原因:对于资源的使用(如 广播BraodcastReceiver、文件流File、数据库游标Cursor、图片资源Bitmap等),若在Activity销毁时无及时关闭 / 注销这些资源,则这些资源将不会被回收,从而造成内存泄漏
解决方案: 在Activity销毁时 及时关闭 / 注销资源
关闭资源代码如下:
// 对于 广播BraodcastReceiver:注销注册
unregisterReceiver()// 对于 文件流File:关闭流
InputStream / OutputStream.close()// 对于数据库游标cursor:使用后关闭游标
cursor.close()// 对于 图片资源Bitmap:Android分配给图片的内存只有8M,若1个Bitmap对象占内存较多,当它不再被使用时,应调用recycle()回收此对象的像素所占用的内存;最后再赋为null
Bitmap.recycle();
Bitmap = null;// 对于动画(属性动画)
// 将动画设置成无限循环播放repeatCount = “infinite”后
// 在Activity退出时记得停止动画
参考连接:WebView内存泄漏–解决方法小结 - 简书 (jianshu.com)
https://juejin.cn/post/6844904067534159880
相关文章:
Android常见内存泄漏场景总结
一、非静态内部类造成的内存泄漏 造成原因:非静态内部类默认会持有外部类的引用,如果内部类的生命周期超过了外部类就会造成内存泄漏。 场景:当Activity销毁后,由于内部类中存在异步耗时任务还在执行,导致Activity实…...
未来已来:Angular、React、Vue.js——前端框架的三大巨头
目录 前言 一、Angular框架 特点和优势 核心技术和应用场景 二、React框架 特点和优势 核心技术和应用场景 三、Vue.js框架 特点和优势 核心技术和应用场景 总结: 前言 在Web前端开发领域,随着技术的不断发展,出现了众多优秀的框…...
Mybatis06-动态SQL
动态SQL 1.什么是动态SQL 什么是动态SQL:动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句. 类似JSTL标签 官网描述: MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接…...
26-LINUX--I/O复用-select
一.I/O复用概述 /O复用使得多个程序能够同时监听多个文件描述符,对提高程序的性能有很大帮助。以下情况适用于I/O复用技术: ◼ TCP 服务器同时要处理监听套接字和连接套接字。 ◼ 服务器要同时处理 TCP 请求和 UDP 请求。 ◼ 程序要同时处理多个套接…...
spring源码解析-(2)Bean的包扫描
包扫描的过程 测试代码: // 扫描指定包下的所有类 BeanDefinitionRegistry registry new SimpleBeanDefinitionRegistry(); // 扫描指定包下的所有类 ClassPathBeanDefinitionScanner scanner new ClassPathBeanDefinitionScanner(registry); scanner.scan(&quo…...
Java 数学计算 - Random类
在Java中,Random类用于生成伪随机数。这个类在java.util包中,你可以使用它来生成整数、浮点数等不同类型的随机数。以下是关于Random类的一些学习笔记和示例。 1. 创建Random对象 首先,你需要创建一个Random对象。默认情况下,如…...
Ubuntu22.04之解决:无法关机和重启问题(二百四十三)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…...
大学数字媒体艺术设计网页设计试题及答案,分享几个实用搜题和学习工具 #媒体#职场发展
现在读书可不像小时候,以前想要校对试题答案,都得找到对应的纸质版答案查看,而且有的还只有答案,没有解析,无法弄清楚答案的由来。但是现在不一样了,现在我们可以通过搜题软件,寻找试题的答案&a…...
【ArcGIS微课1000例】0119:TIFF与grid格式互相转换
文章目录 一、任务描述二、tiff转grid三、grid转tif四、注意事项一、任务描述 地理栅格数据常用TIFF格式和GRID格式进行存储。TIFF格式的栅格数据常以单文件形式存储,不仅存储有R、G、B三波段的像素值,还保存有地理坐标信息。GRID格式的栅格数据常以多文件的形式进行存储,且…...
B3870 [GESP202309 四级] 变长编码
[GESP202309 四级] 变长编码 题目描述 小明刚刚学习了三种整数编码方式:原码、反码、补码,并了解到计算机存储整数通常使用补码。但他总是觉得,生活中很少用到 2 31 − 1 2^{31}-1 231−1 这么大的数,生活中常用的 0 ∼ 100 0…...
WordPress网站更换域名后如何重新激活elementor
在创建WordPress网站时,我们常常需要更改域名。但是,在更换域名后,你可能会遇到一个问题:WordPress后台中的Elementor插件授权状态会显示为不匹配。这时,就需要重新激活Elementor插件的授权。下面我会详细说明如何操作…...
linux cron 执行url
linux cron 执行url 在Linux中,你可以使用curl或wget来执行URL。如果你想要定期执行这个操作,可以使用cron来设置定时任务。 以下是一个使用curl在cron中执行URL的例子: 打开终端。 输入 crontab -e 命令来编辑你的cron作业。 添加一个新…...
压缩视频在线压缩网站,压缩视频在线压缩工具软件
在数字化时代,视频成为了人们记录和分享生活的重要载体。然而,视频文件一般都非常大,这不仅占据了大量的存储空间,也给视频的传输和分享带来了不便。因此,压缩视频成为了许多人必须掌握的技能。本文将详细介绍如何压缩…...
linux经典例题编程
编写Shell脚本,计算1~100的和 首先vi 1.sh,创建一个名为1.sh的脚本,然后赋予这个脚本权限,使用命令chmod 755 1.sh,然后就可以在脚本中写程序,然后运行。 shell脚本内容 运行结果: 编写Shell脚本…...
二叉树的实现(初阶数据结构)
1.二叉树的概念及结构 1.1 概念 一棵二叉树是结点的一个有限集合,该集合: 1.或者为空 2.由一个根结点加上两棵别称为左子树和右子树的二叉树组成 从上图可以看出: 1.二叉树不存在度大于2的结点 2.二叉树的子树有左右之分,次序不能…...
C++笔试强训day41
目录 1.棋子翻转 2.宵暗的妖怪 3.过桥 1.棋子翻转 链接https://www.nowcoder.com/practice/a8c89dc768c84ec29cbf9ca065e3f6b4?tpId128&tqId33769&ru/exam/oj (简单题)对题意进行简单模拟即可: class Solution { public:int dx[…...
【JavaScript】内置对象 - 字符串对象 ⑤ ( 判断对象中是否有某个属性 | 统计字符串中每个字符出现的次数 )
文章目录 一、判断对象中是否有某个属性1、获取对象属性2、判定对象是否有某个属性 二、统计字符串中每个字符出现的次数1、算法分析2、代码示例 String 字符串对象参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String 一、判…...
Linux环境下测试服务器的DDR5内存性能
要在Linux环境下测试服务器的DDR5内存性能,可以采用以下几种方法和工具: ### 测试原理 内存性能测试主要关注以下几个关键指标: - **带宽**:内存每秒能传输的数据量。 - **延迟**:内存访问请求从发出到完成所需的时间…...
19、matlab信号预处理中的中值滤波(medfilt1()函数)和萨维茨基-戈雷滤波滤(sgolayfilt()函数)
1、中值滤波:medfilt1()函数 说明:一维中值滤波 1)语法 语法1:y medfilt1(x) 将输入向量x应用3阶一维中值滤波器。 语法2:y medfilt1(x,n) 将一个n阶一维中值滤波器应用于x。 语法3:y medfilt1(x,n…...
Scala 练习一 将Mysql表数据导入HBase
Scala 练习一 将Mysql表数据导入HBase 续第一篇:Java代码将Mysql表数据导入HBase表 源码仓库地址:https://gitee.com/leaf-domain/data-to-hbase 一、整体介绍二、依赖三、测试结果四、源码 一、整体介绍 HBase特质 连接HBase, 创建HBase执行对象 初始化…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
