Android 常见的内存泄露

Android常见内存泄露分析及MAT与Profiler内存分析时间 1.Java内存分配策略 Java程序运行时的内存分配策略有三种:静态分配、栈式分配和堆式分配。对应的存储区域如下: 静态存储区(方法区):主要存放静态数据、全局static数据和常量。这块内存在程序编译时就已经分配好,并且在程序整个运行期间都存在。 栈区:方法体内的局部变量都在栈上创建,并在方法执行结束时这些局部变量所持有的内存都会自动被释放。 堆区:又称动态内存分配,通常就是指在程序运行时直接new出来的内存。这部分内存在不使用时将会由Java垃圾回收器来负责回收。 2.堆与栈的区别 栈内存: 阅读详情

当一个对象不再需要时,本应该被回收,而被另一个正在使用的对象(可能是静态对象,也有可能是匿名内部类对象,等等)引用导致不能正常被回收,就会一直存活在堆中,造成内存泄露。内存泄露会使程序造成程序OOM(Out Of Memory),导致应用Crash。

单例造成的内存泄漏

由于单例的静态特性,使得单例对象和应用的生命周期一样长。所以被单例对象引用的对象,如果不主动置为null释放对象,那么被引用的对象便和单例对象“共生死”,即使被引用的对象不需要了,也不能被回收,从而造成内存泄露。
如例子:

public class AppManager {
    private static AppManager instance;
    private Context context;
    private AppManager(Context context) {
        this.context = context;
    }
    public static AppManager getInstance(Context context) {
        if (instance != null) {
            instance = new AppManager(context);
        }
        return instance;
    }
}

这样写本来没错,如果你这么用的话:

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        AppManger appManager = AppManager.getInstance(this);
    }
}

那MainActivity就别想被回收了,给我老实待在堆内存中吧!!原因是被单例AppManager所引用。改善的方法:

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        AppManger appManager = AppManager.getInstance(getApplicationContext());
    }
}

这样使用的话,MainActivity就不会被引用,如果没有其他地方引用MainActivity的话,等finish了,就可以等着被回收了。

非静态内部类造成的内存泄露

非静态内部类(包括匿名内部类)会持有外部类对象的强引用(如 Activity),所以很容易导致内存泄露,比如 Handler, Runnable 。

Handler内存泄露
public class MainActivity extends AppCompatActivity {
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // TODO Something
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        loadData();
        finish();
    }
    private void loadData() {
        Message message = Message.obtain();
        mHandler.sendMessageDelayed(message, 100000);
    }
}

因为mHandler是MainActivity的内部类,所以隐式持有MainActivity这个实例。由于Handler还有没有处理的Message,而Message持有mHandler实例,此时即使MainActivity关掉了,内存资源也无法及时被回收,造成内存泄露。解决办法:

public class MainActivity extends AppCompatActivity {
    private MyHandler mHandler = new MyHandler(this);
    private TextView mTextView ;
    private static class MyHandler extends Handler {
        private WeakReference<Context> reference;
        public MyHandler(Context context) {
            reference = new WeakReference<>(context);
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = (MainActivity) reference.get();
            if(activity != null){
                activity.mTextView.setText("");
            }
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView)findViewById(R.id.textview);
        loadData();
        finish();
    }
    private void loadData() {
        //...request
        Message message = Message.obtain();
        mHandler.sendMessageDelayed(message, 100000);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }
}
  1. 把非静态内部类声明为静态内部类(其实就相当于单独的一个类,写在某个类里面而已),这样的话mHandler就不再直接持有MainActivity实例了。
  2. 因为要用到MainActivity实例,使用弱引用方式引用MainActivity实例,这样即使mHandler还有没处理的Message,等MainActivity关掉了,MainActivity资源也可以正常被回收。
  3. 虽然步骤1和2避免了Activity泄漏,不过Looper线程的消息队列中还是可能会有待处理的消息,所以我们在Activity的Destroy时或者Stop时应该调用mHandler的removeCallbacksAndMessages或者removeCallbacks移除消息队列中的消息。
Runnable内存泄露
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(10000);
            }
        }).start();
        finish();
    }
}

和Handler一样,因为new出来的Thread匿名内部类也隐式持有MainActivity实例,所以会造成内存泄露,解决的办法如解决Handler内存泄露的原理一样,不再赘述。

资源未关闭造成的内存泄露

  • BroadcastReceiver,ContentObserver 之类的没有解除注册

  • Cursor,Stream 之类的没有 close

  • 无限循环的动画在 Activity 退出前没有停止

  • 一些其他的该 release 的没有 release,该 recycle 的没有 recycle… 等等。

使用 Python+PaddleOCR 实现图文识别:从入门到精通 在当今数字化时代,图文识别技术的应用越来越广泛,如文档数字化、信息提取等。PaddleOCR 是百度开源的一款强大的 OCR 工具包,它集成了多种先进的算法和模型,能够高效准确地进行图文识别。本文将详细介绍如何使用 PaddleOCR 和 Python 实现图文识别,并给出具体的代码和步骤。 阅读详情

相关推荐

PCB设计实践(三十二)PCB设计遇到大电流时的设计技巧

本文系统阐述10A至数百安培PCB设计的六大关键技术。载流能力优化强调铜厚选择(2-4oz)、线宽计算及并联结构;热管理提出散热孔阵列、铜基板嵌入等方案;布局策略包括功率分区和低阻抗路径设计;材料工艺推荐铝基板、陶瓷基板等高效解决方案;安全设计涵盖电气隔离与保护电路;验证环节需结合热仿真与实测。典型150A电机驱动板案例显示,通过4oz铝基板、散热孔阵列等设计,可实现温升≤45℃的稳定运行。核心在于铜厚线宽协同、主动散热及严格验证。

致力于硬件设计、人工智能知识及技术的分享,不断鞭策自己成长,共同进步! 4229

Android中常见的内存泄露

Android中常见的内存泄露有以下几种:1.单例造成的内存泄露

喵喵喵喵喵? 342

在Cursor IDE中集成Datadog监控:自然语言查询实战指南

在云原生和微服务架构中,可观测性(Observability)已成为保障系统稳定性的核心技术支柱。其核心原理是通过日志(Logs)、指标(Metrics)和追踪(Traces)三大支柱,实时采集并呈现系统的运行状态。这项技术的价值在于,它让开发者能够透视复杂的分布式系统,快速定位性能瓶颈与故障根因。在实际的工程实践中,开发人员常常需要在编码环境与监控平台之间频繁切换,这种上下文切换严重影响了排障效率。本文聚焦于如何利用Model Context Protocol(MCP),将强大的Datadog可观测性平台

weixin_42519772的博客 348

Android leak内存,GitHub - jin870132/memoryleakdemo: 安卓内存泄露几种常见形式及解决方案...

安卓内存泄露几种常见形式及解决方案一.前言1.内存溢出与内存泄露内存溢出(oom),是指程序在申请内存时,没有足够的内存空间供其使用,出现oom;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。内存泄露 (memory leak),是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memor...

weixin_39559277的博客 300

【鸿蒙南向开发】OpenHarmony音频驱动audio适配方案

这份鸿蒙(HarmonyOS NEXT)文档包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

HarmonyOS_666的博客 4511

【Telephony】Telephony总纲!Phone进程流程(AOSP)

整个Framework层的Telephony框架运行在一个叫做Phone(com.android.phone)的进程中。 Phone进程启动的过程中,会初始化非常多的分支功能,SIM卡流程初始化就是其中之一,所以我觉得有必要写一下Phone进程的框架

weixin_44513784的博客 1975

Android下常见的内存泄露

因为Android使用Java作为开发语言,很多人在使用会不注意内存的问题。 于是有时遇到程序运行时不断消耗内存,最终导致OutOfMemery,程序异常退出,这就是内存泄露导致的。 我们现在就来总结一下可能导致内存泄露的情况: 查询数据库而没有关闭

Alfred的贼窝 1003

从理论到实践:利用FilterSolutions高效设计7阶椭圆低通滤波器

本文详细介绍了如何利用FilterSolutions软件高效设计7阶椭圆低通滤波器。文章从理论入手,对比了巴特沃斯、切比雪夫等经典滤波器特性,阐述了在要求高衰减陡度(如62dB抑制)和严格通带波纹(0.2dB)时,椭圆滤波器是最优选择。通过分步实战教程,指导读者完成从软件参数设置、性能验证到实际电路布局与调试的全过程,助力射频与高速数字信号处理工程师将理论转化为可靠设计。

jupi8的博客 559

Android常见内存泄露及优化方案

简介 如果一个无用对象(不需要再使用的对象)仍然被其他对象持有引用,造成该对象无法被系统回 收,以致该对象在堆中所占用的内存单元无法被释放而造成内存空间浪费,这中情况就是内存泄 露。在 Android 开发中,一些不好的编程习惯会导致我们的开发的 app 存在内存泄露的情况。下面介绍总结一些在 Android 开发中常见的内存泄露场景及优化方案。 单例导致内存泄露 单例模式在 Android...

浪克oo的博客 641

有限元之有限元空间的构造

主要介绍有限元的空间构造方法。

欢迎各位大佬光临“寒舍”!请多多指点,共同进步! 762

python基础:工作会用到的90%的python代码都在这了(万字详解!)

Python 备忘单是 Python 3 编程语言的单页参考表 著名的“Hello World”程序在 Python 中的实现 Python 不能在没有赋值的情况下声明变量 变量可以存放不同类型的值 内置数据类型 序列指一批有序的元素,集合指一批无序且不重复的元素查看: 数据类型 查看: 字符串 查看: 列表 查看: 判断 查看: 循环 查看: 函数 查看: 文件处理 表示 x 和 y 的商, 表示 x 和 y 的底商,另见 StackOverflow f-字符串 (Python 3.6+) 查看

数据知道的博客 1万+

Android中常见的内存泄露分析

前言 Android应用因为本身可用内存的限制,需要特别重视内存泄露的问题,本文总结了Android中常见的一些内存泄露原因及避免方式。 一、单例造成的内存泄露 由于单例的静态特性使得单例的生命周期和应用的生命周期一样长,这说明,如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么该对象将不能被正常回收,这就导致了内存泄露。 例,如下的写法是我们

努力向前的小蜗牛 1686

【立创EDA-PCB设计基础】1.嘉立创EDA专业版软件安装+PCB基本概念+原理图绘制

本文详解PCB基本概念以及实现MCU最小系统原理图的绘制(原理图包括MCU芯片GD32F103C8T6、外部晶振、输出端口、USB输入口、5v转3v3稳压输出、复位按键、唤醒按键、LED)及嘉立创EDA专业版软件安装。为本专栏【立创EDA-PCB设计基础】后面章节实现PCB绘制做准备。

嵌入式阿齐Archie 3万+

Android 内存优化——常见内存泄露及优化方案

如果一个无用对象(不需要再使用的对象)仍然被其他对象持有引用,造成该对象无法被系统回 收,以致该对象在堆中所占用的内存单元无法被释放而造成内存空间浪费,这中情况就是内存泄 露。 在 Android 开发中,一些不好的编程习惯会导致我们的开发的 app 存在内存泄露的情况。下面介 绍一些在 Android 开发中常见的内存泄露场景及优化方案。 单例导致的内存泄露 单例模式在 Android 开发...

qq_36451275的博客 209

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

安卓内存泄露几种常见形式及解决方案

一.前言1.内存溢出与内存泄露 内存溢出(oom),是指程序在申请内存时,没有足够的内存空间供其使用,出现oom;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。内存泄露 (memory leak),是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memory leak会最终会导致oom!

金福林的博客 1519

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Android下常见的内存泄露 经典

转自:http://www.linuxidc.com/Linux/2011-10/44785.htm 因为Android使用Java作为开发语言,很多人在使用会不注意内存的问题。 于是有时遇到程序运行时不断消耗内存,最终导致OutOfMemery,程序异常退出,这就是内存泄露导致的。 我们现在就来总结一下可能导致内存泄露的情况: 查询数据库而没有关闭Cursor 在Andro

以现在的努力程度之低,谈狗屁的未来,屎的梦想!!! 2万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

android 常见内存泄露,android中的内存泄露查找与常见的内存泄露案例分析

常见的内存泄露查找方法请参见:http://hukai.me/android-performance-patterns/这篇文章是google发布的android性能优化典范示例,对于渲染、内存GC与电量消耗都做了好的示范。这里我总结了下,android中常见的内存泄露1、类中调用registerReceiver后未调用unregisterReceiver().在调用registerReceive...

weixin_39626180的博客 303

java 匿名内部类内存泄露,【内存泄露】Android常见Java内存泄露分析

前言自从工作以来,有很长一段时间没发博客了。很久之前说要对我的个人开源库AppInject原理做一个讲解也搁置了很久...这里挖个坑,11月之内把这块补齐...最近接手了项目中比较老的一个模块(可能有8年以上的历史了),性能组的同学扫出了很多模块内存在的内存泄露问题,然后我最近工作的状态的就是一边赶需求一边修复内存泄露(同时还要补上单测)。解决了蛮多的内存泄漏问题,也对这一块有了更多的理解,这里做...

weixin_39604350的博客 336

Android中常见的内存泄露及解决办法汇总

  内存泄露就是指该被GC垃圾回收的,由于有另外一个对象仍然在引用它,导致无法回收,造成内存泄露,过多的内存泄露会导致OOM。   android中的内存泄露通常是Activity或者Fragment的泄露。下文分析以Activity展开,Fragment同理。 1. 非静态内部类、匿名内部类 2. 静态的View 3. Handler 4. 监听器(各种需要注册的Listener...

Hello CYC 1万+
上一篇: Android 内存 - 垃圾回收(GC)机制
下一篇: Android 内存泄露分析
JohanMan
博客等级 码龄10年 72粉丝 131原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值