关于内存泄漏,一般像单例模式的使用不当啊、集合的操作不当啊、资源的缺乏有效的回收机制啊、Handler、线程的使用不当等等都有可能引发内存泄漏。
总结为一张图:
真正遇到过的内存溢出,是有一次查表,总共有几百M的数据被我一次性查出来,拿到这些数据后进行了一个StringBuffer的拼接,才0.5M就OOM了。后来处理方式就是每次拿10条数据库里面的东西,用完就=null。
内存优化,上面的都将的差不多了,那我说一下不一样的 其实性能优化的大多数方案都会侧面的有 内存优化的功能 比如:apk包体积优化,就会减少应用所需系统内存,还有 界面优化(层级减少、界面尽量不刷新或者局部刷新)也会优化内存,
看了大家的回答,感觉都讲得很不错。我这里说几个大家在开发中关于内存优化的几个细节。
2.集合操作不当引发的内存泄漏 (1)对于HashMap,不使用动态改变hashCode的作为key对象 (2)对于HashSet,可以重写对象的equal和hashCode方法,增减特定的key的hashCode,使得每一个对象唯一 (3)如果发现remove之后,集合的数目没有改变,对于HashMap可以进行SetKey排查
由于JVM有垃圾回收机制,因此,java内存要注意的问题相对c语音就大幅减少。主要可分为内存泄漏和内存溢出。
1,内存泄漏,本质是:生命周期长的对象持有了生命周期短的对象的引用。 常见场景: 1)资源对象未关闭导致内存泄漏,例如File、Cursor 2)静态类强引用,例如:Handler、webview、广播注册 2,内存溢出,本质是:APP内存超过了系统的上限 常见场景: 1)创建了超大文件,例如:大的图片一次性加载、text文件一次性加载 2)申请内存的速度超出了gc的速度,例如:递归没有终止、循环创建大量对象(线程)、大量的内存泄漏累积
内存优化,针对这两种情况进行注意就可以了,定期对APP进行内存检查即可。 当然,还有一种内存的兜底方案: 实现低内存状态回调,当系统内存不足,调用api时,执行自动重启APP、杀掉推送、关闭后台service等等操作
避免静态内部类的引用。比如A类中有静态变量B。这是只要B被应用,就会导致A也不能回收。 没明白你的意思,难道要用非静态内部类避免内存泄漏
A类中有静态变量B,B被引用。并不会导致A类对应的对象不能回收。。 例如: class A{ public static B mB = new B(); }
使用: A a = new A(); 这个a和mB之间没有引用的关系。
你使用的时候也是:A.mB而不是a.mB
为什么这么多说软引用的,谷歌都不推荐 https://blog.csdn.net/zhangphil/article/details/80634204, 安卓开发中也不存在必须要用的软引用的地方,要么就硬引用,要么就被释放,不需要模棱两可
导致内存泄漏的原因只要有以下几种 1单例静态实例使用对象的引用 例:单例静态实例中使用了Activity context 解决方法:单例静态实例中不使用Activity context 而是使用application context 2资源末回收 例:数据库 文件读取流末关闭 解决方法:及时关闭数据库 文件读取流末关闭 3注册事件末注销 例:广播事件 EventBus注册后 无使用不注销掉 解决方法:无使用注销掉注册事件 4线程池的对象引用在后台执行 5匿名内部类/非静态内部类操作不当 例:在Activity中创建一个内部类handle 因为在发送消息后 handle的message持有Activity的对象引用 而message又放在消息队列中等待轮询处理 Activity可能退出后handle可能还末处理或者正在处理 这样就会导致Activity无法被回收 导致内存泄漏 解决方法:使用静态内部类+弱引用 6集合只增不减 例:当一个对象放入到ArrayList集合中 那这个集合就持有该对象的引用 当我们不需要这个对象时如果没有将它从集合中移除 这样只要这个集合还在这个对象就已经造成内存泄漏 解决方法:无使用的集合对象 从集合remove,或者clear集合,以避免内存泄漏。
文章已经不在了
Activity
Ssuiyingsen commentedon Apr 2, 2019
关于内存泄漏,一般像单例模式的使用不当啊、集合的操作不当啊、资源的缺乏有效的回收机制啊、Handler、线程的使用不当等等都有可能引发内存泄漏。
原因:单例模式里的静态实例持有对象的引用,导致对象无法被回收,常见为持有Activity的引用
优化:改为持有Application的引用,或者不持有使用的时候传递。
原因:集合只增不减
优化:有对应的删除或卸载操作
原因:线程持有对象的引用在后台执行,与对象的生命周期不一致
优化:静态实例+弱引用(WeakReference)方式,使其生命周期一致
原因:内部类持有对象引用,导致无法释放,比如各种回调
优化:保持生命周期一致,改为静态实例+对象的弱引用方式(WeakReference)
原因:BroadcastReceiver,File,Cursor,IO流,Bitmap等资源使用未关闭
优化:使用后有对应的关闭和卸载机制
原因:Handler持有Activity的引用,其发送的Message中持有Handler的引用,当队列处理Message的时间过长会导致Handler无法被回收
优化:静态实例+弱引用(WeakReference)方式
内存溢出:
原因:
1.内存泄漏长时间的积累
2.业务操作使用超大内存
优化:
1.调整图像大小后再放入内存、及时回收
2.不要过多的创建静态变量
Moosphan commentedon Apr 2, 2019
总结为一张图:
q514414232 commentedon Apr 3, 2019
真正遇到过的内存溢出,是有一次查表,总共有几百M的数据被我一次性查出来,拿到这些数据后进行了一个StringBuffer的拼接,才0.5M就OOM了。后来处理方式就是每次拿10条数据库里面的东西,用完就=null。
979451341 commentedon Apr 3, 2019
内存优化,上面的都将的差不多了,那我说一下不一样的
其实性能优化的大多数方案都会侧面的有 内存优化的功能
比如:apk包体积优化,就会减少应用所需系统内存,还有 界面优化(层级减少、界面尽量不刷新或者局部刷新)也会优化内存,
MoJieBlog commentedon Apr 19, 2019
看了大家的回答,感觉都讲得很不错。我这里说几个大家在开发中关于内存优化的几个细节。
...
其实关于内存的优化还有好多,欢迎大家补充。
nealkafuly commentedon Nov 14, 2019
2.集合操作不当引发的内存泄漏
(1)对于HashMap,不使用动态改变hashCode的作为key对象
(2)对于HashSet,可以重写对象的equal和hashCode方法,增减特定的key的hashCode,使得每一个对象唯一
(3)如果发现remove之后,集合的数目没有改变,对于HashMap可以进行SetKey排查
yline commentedon Dec 20, 2019
由于JVM有垃圾回收机制,因此,java内存要注意的问题相对c语音就大幅减少。主要可分为内存泄漏和内存溢出。
1,内存泄漏,本质是:生命周期长的对象持有了生命周期短的对象的引用。
常见场景:
1)资源对象未关闭导致内存泄漏,例如File、Cursor
2)静态类强引用,例如:Handler、webview、广播注册
2,内存溢出,本质是:APP内存超过了系统的上限
常见场景:
1)创建了超大文件,例如:大的图片一次性加载、text文件一次性加载
2)申请内存的速度超出了gc的速度,例如:递归没有终止、循环创建大量对象(线程)、大量的内存泄漏累积
内存优化,针对这两种情况进行注意就可以了,定期对APP进行内存检查即可。
当然,还有一种内存的兜底方案:
实现低内存状态回调,当系统内存不足,调用api时,执行自动重启APP、杀掉推送、关闭后台service等等操作
pinpoy commentedon Feb 24, 2020
yline commentedon Feb 26, 2020
A类中有静态变量B,B被引用。并不会导致A类对应的对象不能回收。。
例如:
class A{
public static B mB = new B();
}
使用:
A a = new A();
这个a和mB之间没有引用的关系。
你使用的时候也是:A.mB而不是a.mB
aositeluoke commentedon Dec 5, 2020
paranoidharmony commentedon Jul 12, 2021
为什么这么多说软引用的,谷歌都不推荐 https://blog.csdn.net/zhangphil/article/details/80634204, 安卓开发中也不存在必须要用的软引用的地方,要么就硬引用,要么就被释放,不需要模棱两可
mlinqirong commentedon Dec 24, 2021
导致内存泄漏的原因只要有以下几种
1单例静态实例使用对象的引用
例:单例静态实例中使用了Activity context
解决方法:单例静态实例中不使用Activity context 而是使用application context
2资源末回收
例:数据库 文件读取流末关闭
解决方法:及时关闭数据库 文件读取流末关闭
3注册事件末注销
例:广播事件 EventBus注册后 无使用不注销掉
解决方法:无使用注销掉注册事件
4线程池的对象引用在后台执行
5匿名内部类/非静态内部类操作不当
例:在Activity中创建一个内部类handle 因为在发送消息后 handle的message持有Activity的对象引用 而message又放在消息队列中等待轮询处理 Activity可能退出后handle可能还末处理或者正在处理 这样就会导致Activity无法被回收 导致内存泄漏
解决方法:使用静态内部类+弱引用
6集合只增不减
例:当一个对象放入到ArrayList集合中 那这个集合就持有该对象的引用 当我们不需要这个对象时如果没有将它从集合中移除 这样只要这个集合还在这个对象就已经造成内存泄漏
解决方法:无使用的集合对象 从集合remove,或者clear集合,以避免内存泄漏。
yihu5566 commentedon Jun 16, 2022
文章已经不在了
luckilyyg commentedon Jun 16, 2022