1. 内存溢出
内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用,就会出现out of memory。
内存溢出常见场景:
- 栈溢出:循环调用自己的方法,不断在栈中压栈。
- 堆溢出:在堆中创建了很多对象或存储了很大的数据,造成堆中放满了对象,再次有对象申请时,发现内存不足,就会报oom。
- GC回收极限:回收时间过长,每次有98%的时间在回收内存,但只回收了不到2%的内存,多次GC后连续不断回收2%的情况下才会抛出异常。如果没有抛出,那就是GC回收的这点内存又会堆满,迫使GC又进行回收,造成恶性循环,使GC的使用率一直在100%工作,而没有任何效果。
1.1 如何加载Bitmap防止内存溢出
- 对图片进行内存压缩
- 高分辨率的图片放入对应文件夹
- 内存复用
- 及时回收
2. 内存泄漏
内存泄漏:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可以忽略,但内存泄漏堆积后果很严重,无论多少内存,迟早被占光。类似于内存上不可用的漏洞。
内存泄漏常见场景:
- 创建和应用生命周期一样的单例对象
不正确使用是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄漏。
- 创建匿名内部类的静态对象
- 未关闭资源
- 长时间存在的集合容器中创建生命周期短的对象
2.1 Thread是如何造成内存泄漏的,如何解决?
在主线程里创建了一个thread,里面的run方法里在执行耗时的操作,当thread正在执行时,activity发生了横竖屏切换,那么原来的activity就应该先被销毁再进行创建,可是由于内部类持有外部类的引用,造成了thread在运行时还持有activity的引用,导致activity不能被回收,这时候就会发生内存泄露。
如何解决:
- 设置静态内部类
- 把持有的外部类改成弱引用,弱引用是当GC回收时,不管内存是否充足,只要发现弱引用的对象就进行回收
2.2 Handler导致的内存泄漏的原因以及如何解决
因为Handler是内部类,如果Handler的Looper和MessageQueue在主线程,那么Handler会持有外部类的引用,如果activity销毁时,Handler还在运行,那么就会造成内存泄漏。
如何解决:
- 将它定义成静态的内部类,静态内部类不持有外部类的引用
- 把持有的外部类引用改为弱引用,因为有可能需要访问外部类成员