什么是内存泄漏?
一个无用的对象,仍然被其他对象持有引用,造成该对象无法被系统回收,导致该对象在堆中所占有的内存单元无法被释放而造成内存空间浪费,这就是内存泄漏.
什么是堆?
https://blog.csdn.net/weixin_46269963/article/details/120010419?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2defaultCTRLISTRate-1-120010419-blog-77833808.pc_relevant_multi_platform_whitelistv4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2defaultCTRLISTRate-1-120010419-blog-77833808.pc_relevant_multi_platform_whitelistv4&utm_relevant_index=2
堆(Heap):是应用程序在运行的时候请求操作系统分配给自己的内存,一般是申请/给予的过程,C/C++分别用malloc/New请求分配Heap,用free/delete销毁内存。由于从操作系统管理的内存分配所以在分配和销毁时都要占用时间,所以用堆的效率低的多!但是堆的好处是可以做的很大,C/C++对分配的Heap是不初始化的。
什么是栈?
栈(Stack):是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有FILO的特性,在编译的时候可以指定需要的Stack的大小。
堆栈(heap and stack)的概念在计算机领域中不容忽视。虽然堆栈常被连着念,堆与栈是两个相对的概念:堆指先进先出(first in first out),栈指先进后出(first in last out) ;
引起内存泄漏的几种场景以及解决方式
1.单例导致内存泄漏
单例的静态特性使得ta的生命周期和应用的生命周期一样长,如果一个对象已经没有用处了,但是单例还持有ta的引用,那么在整个应用的生命周期中ta都不能被正常的回收,从而导致内存泄漏.
public class AppSettings {
private static AppSettings sInstance;
private Context mContext;
private AppSettings(Context context) {
this.mContext = context;
}
public static AppSettings getInstance(Context context) {
if (sInstance == null) {
sInstance = new AppSettings(context);
}
return sInstance;
}
}
像上面的单例,在调用getInstance 方法时,如果传入的是Activity、Service这类上下文,就会导致内存泄漏!
例如传入的上下文是Activity,那么上述单例类就持有了Activity的引用,当我们退出Activity页面时,这个Activity就不在使用了,但是因为单例类作为静态单例,它还是继续持有这个Activity的引用,导致这个Activity无法被系统回收释放,这就造成了内存泄漏;