[Java、Android面试]_05_内存泄漏和内存溢出
本人今年参加了很多面试,也有幸拿到了一些大厂的offer,整理了众多面试资料,后续还会分享众多面试资料。
整理成了面试系列,由于时间有限,每天整理一点,后续会陆续分享出来,感兴趣的朋友可关注+收藏
文章目录
- 1. 内存泄漏
- 2. 内存溢出
1. 内存泄漏
内存泄露是指申请了一块内存,但没有及时释放,这块内存就会一直被占用而无法被分配,这样就出现了内存泄露。
(1)内存泄露的四种状态:
常发性内存泄漏: 发生泄露的代码经常性被执行,每次都会泄露一块内存;
偶发性内存泄露: 发生内存泄露的代码只有在特定环境和操作过程中才会发生;
一次性内存泄露: 发生内存泄露的代码仅会被执行一次,或者由于算法上的缺陷,导致总会有一块且仅一块内存发生泄露。例如:在类的构造函数中分配内存,在析构函数中却没有释放内存,这里就仅发生一次。
隐式内存泄漏: 程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。
(2)内存泄露实例:
单例、线程、hander都可能造成内存泄露。下面展示单例造成的内存泄露实例:
//单例需要传入一个Context,所以这个Context的生命周期的长短至关重要:
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context.getApplicationContext();
// 1.这里传入一个Application的Context:这将没有任何问题,因为单例的 生命周期和Application的一样长
//this.context = context;
// 2、传入的是Activity的Context:当这个Context所对应的Activity退出时,由于该Context和Activity的生命周期一样长(Activity间接继承于Context),所以当前Activity退出时它的内存并不会被回收,因为单例对象持有该Activity的引用。
}
public static AppManager getInstance(Context context) {
if (instance != null) {
instance = new AppManager(context);
}
return instance;
}
}
单例的静态特性使得单例的生命周期和应用的生命周期一样长,这就说明了如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。
怎样解决呢?
可以是用对context使用软引用或弱引用的方式进行引用。
2. 内存溢出
系统无法分配需要的内存,就会造成OOM.
产生原因及如何避免:
(1)图片过大导致OOM:对图片进行质量压缩或尺寸压缩
(2)对不需要的使用的资源进行释放内存
(3)查询数据库没有关闭游标
(4)在Activity生命周期onPause()、onStop()、onDestory()中适当释放资源