Android 内存泄露溢出,Android中的内存泄漏和内存溢出.md

本文探讨了Java中常见的内存泄漏原因,如单例模式、非静态内部类、Handler及线程引起的内存泄漏,并提供了相应的解决方案,如使用弱引用、静态内部类和及时关闭资源。同时介绍了LeakCanary工具在检测内存泄漏中的作用,以及内存泄漏与内存溢出的区别。理解并掌握这些策略有助于提高应用的性能和稳定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念

内存泄漏是因为持有对象长期引用,导致对象无法被 GC 回收。

为了避免这种情况,我们可以选择在对象生命周期结束的时候,解除绑定,将引用置为空,或者使用弱引用。

例子

单例模式导致内存泄露

传入的context为act,但单例的生命周期是app

非静态内部类、匿名内部类导致内存泄露(静态变量持有Act,非静态内部类的静态实例 )

它们会隐式的持有外部类的引用,长期持有该引用(比如写个循环)就会导致内存泄漏,使用静态内部类和弱引用来代替它们。(因为静态的内部类不会持有外部类的引用)

Handler导致内存泄漏

Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。

在Message中存在一个 target,是Handler的一个引用,如果Message在Queue中存在的时间越长,就会导致Handler无法被回收。

如果Handler是非静态的,(因为持有外部activity的引用)会导致Activity或者Service不会被回收。

解决方法 :

静态内部类+弱引用

创建一个静态Handler内部类,然后对Handler持有的对象使用弱引用)

静态内部类+弱引用。相当于activity没关闭的时候,act有强弱两种引用,关闭的时候,只有弱引用。

非静态内部类+api clean掉message

线程造成的内存泄漏

执行一些长期运行的任务,避免在这些任务中持有 Activity 对象的引用,如果持有了引用的话,我们应该在对象生命周期结束的时候,释放引用。

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

对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。

LeakCanary

LeakCanary的内存泄露提示一般会包含三个部分:

第一部分(LeakSingle类的sInstance变量)引用第二部分(LeakSingle类的mContext变量), 导致第三部分(MainActivity类的实例instance)泄露.

Java的GC内存回收机制

cc4f2fd5dc02

当我们向上寻找,一直寻找到GC Root的时候,此对象不会进行回收,例如,一个Activity。那么如果我们向上寻找,直到找到GC Root对象的时候,就说明它是不可以回收的,例如,我定义了一个int a;但是这个数据,我整个页面或者说整个项目都没有用到,则这个对象会被GC掉。

GC的引用点

java栈中引用的对象

方法静态引用的对象

方法常量引用的对象

Native中JNI引用的对象

Thread——“活着的”线程

内存溢出

cc4f2fd5dc02

瞬间大内存:图片加载

内存泄漏和内存溢出区别

内存溢出是指程序在申请内存的时候,没有足够的内存可以分配,导致Out Of Memory错误,也就是OOM。

内存泄漏:对象都有生命周期的,在生命周期完成之后,就该被垃圾回收和释放,如果得不到及时的释放,就会一直占用内存,造成内存泄漏。随着内存泄漏的堆积,可能导致oom。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值