内存泄漏
用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。即所谓的内存泄漏。内存泄漏是造成应用程序OOM(内存溢出)的主要原因之一!
怎样避免内存泄漏
1.单例模式引发的内存泄漏:
单例模式里的静态实例持有对象的引用,导致对象无法被回收,常见为持有Activity的引用
优化:改为持有Application的引用,或者不持有使用的时候传递。
2.集合操作不当引发的内存泄漏:
集合只增不减
3.线程的操作不当引发的内存泄漏:
线程持有对象的引用在后台执行,与对象的生命周期不一致。
修改为静态实例+弱引用(Weakrefrence)方式,使其生命周期一致
4.匿名内部类/非静态内部类操作不当引发的内存泄漏:
内部类持有对象引用,导致无法释放,比如各种回调。应当保持生命周期一致,改为静态实例+对象的弱引用方式(WeakReference)
5.常用的资源未关闭回收引发的内存泄漏:
BraodcastReceiver,File,Cursor,IO流,Bitmap等资源使用未关闭
6.Handler使用不当造成的内存泄漏:
Handler持有Activity的引用,其发送的Message中持有Handler的引用,当队列处理Message的时间过长会导致Handler无法被回收
优化:静态实例+弱引用(Weakrefrence)方式
销毁对象时候清空队列里的Message
7.注册对象未被反注册
内存溢出
内存溢出是指虚拟机内存耗尽,无法为新对象分配内存,导致引用崩溃。典型的情况为加载多张大图,导致内存耗尽。
怎样避免内存溢出
1.调整图像大小后再放入内存、及时回收
2.不要过多的创建静态变量
内存问题
Android内存异常通常会引起2个问题:
异常
异常包括 OOM、内存分配失败这些崩溃,也包括因为整体内存不足导致应用被杀死、设备重启等问题。
卡顿
Java 内存不足会导致频繁 GC,这个问题在 Dalvik 虚拟机会更加明显。而 ART 虚拟机在内存管理以及回收策略上都做大量优化,内存分配和 GC 效率相比提升了 5~10 倍。如果想具体测试 GC 的性能,可以通过发送 SIGQUIT 信号获得 ANR 日志。
adb shell kill -S QUIT PID
adb pull /data/anr/traces.txt
这里补充一点,导致GC频繁执行的原因:
内存抖动:大量的对象被创建又在短时间内马上被释放。
瞬间产生大量的对象会严重占用Young Generation的内存区域,当达到阀值,剩余空间不够的时候,也会触发GC。
Android内存警告
Android系统为每一个App分配可用的内存堆,并且负责执行垃圾回收(从内存中移除旧的内容)。在内存正在处于临界水平时,处于运行(或缓存)状态的App会释放内存来防止自己被清理掉。onTrimMemory方法会告诉你App被缓存在什么位置,以及如何释放内存,从而来保证App不会被从内存中移除。如果App正在运行,并存在内存问题,onTrimMemory方法会发出以下的警告:
TRIM_MEMORY_RUNNING_MODERATE
首先发出TRIM_MEMORY_RUNNING_MODERATE警告。
TRIM_MEMORY_RUNNING_LOW
如果继续执行,将会发出TRIM_MEMORY_RUNNING_LOW警告,就像是黄灯警示。这时系统会开始释放释放无用资源来提高系统性能。
TRIM_MEMORY_RUNNING_CRITICAL
如果仍然继续执行并且没有释放资源,将会发出红灯警告:TRIM_MEMORY_RUNNING_CRITICAL。此时,系统会杀掉后台进程来获取更多的内存。同时,这将降低你App的性能。
TRIM_MEMORY_UI_HIDDEN
当回调TRIM_MEMORY_UI_HIDDEN时,是指App刚从前台转为后台,这是一个释放大量UI资源的大好时机。此时App在缓存的App列表中。如果有问题,此App的进程将会被杀死。作为一个后台程序,尽可能地多释放资源,这样恢复的时候将会比纯粹的重启(译者注:App由于内存不足被杀死后的重启)更加快速。有3个级别:
TRIM_MEMORY_BACKGROUND
App处于缓存应用列表中,被杀掉的风险不高。
TRIM_MEMORY_MODERATE
App有被杀掉的风险。
TRIM_MEMORY_COMPLETE
这是“下一个被杀掉的就是此App”的警告,此时应该释放的所有非关键的资源从而恢复应用的状。
如何进行内存优化
1 布局优化 不要嵌套布局 不需要显示的布局要gone这样就不会绘制
2 列表及adapter优化 滑动停止再加载图片
3 背景和图片等内存分配优化
4 避免ANR
5 当service完成后,尽量关闭它
6 在UI不可见的时候,释放掉一些只有UI使用的资源
7 在系统内存紧张的时候,尽可能多的释放掉一些非重要资源
8 避免滥用Bitmap导致的内存泄漏
9 使用针对内存优化的数据容器
10 避免使用依赖注入的框架
11 避免静态变量和单例的滥用
内存优化的工具
常用的3种
工具 | 目标 | 能力 |
---|---|---|
Memory Profiler | 内存泄漏、内存抖动、应用卡顿等 | 定位+实时追踪 |
Memory Analyzer | 内存泄漏、内存占比 | 定位+发现 |
Leak Canary | Activity内存泄漏 | 定位+自动发现 |