前言
内存泄漏是在平时开发与面试中都比较常见的问题,好记性不如烂笔头。今日来有模样的总结一下(这次排版很用心的!!~)~
基础巩固
内存泄漏(Memory Leak)
java中的内存泄漏是指某些对象已经没有使用价值了,但他依旧在直接或者间接引用到gc root 导致无法被GC回收。 在C++中也称为野指针
Android中会因为生命周期的长短不一致而导致内存泄漏: 比如说当Activity onDestroy被调用之后,那么activity中的view和相关的bitmap都应该被回收。 但是如果某个后台线程或者某个static持有这个activity的引用,那么activity对应的内存就不能被回收。这就容易导致内存耗尽,然后最终导致OOM而崩溃。
内存溢出(OOM)
当应用程序申请的java heap空间超过Dalvik VM时,溢出。 注意:OOM并不代表内存不足,只要申请的heap超过Dalvik VM时,即使手机内存充足也会溢出。
Java程序运行时的三种内存分配策略
栈(Stack)
当方法被执行时,方法体内的局部变量(包括基础数据类型、对象的引用)都在栈上创建,并在方法执行结束时这些局部变量所持有的内存将会自动被释放。因为栈内存分配运算内置与处理器的指令集中,效率很高,但是分配的内存容量有限。
堆(Heap)
又称为动态内存分配,通常就是指在程序运行时直接new出来的内存,也就是对象的实例。这部分内存在不使用时将会由Java垃圾回收器来负责回收。【巩固一下内存泄漏的原理:就是 new 出来的 Object 放在 Heap 上无法被GC回收】
静态存储区(方法区)
主要存放静态数据、全局static数据和常量。这块内存在程序编译时就已经分配好,并且在程序整个运行期间都存在
如何应对内存泄漏
LeakCanary是一个检测内存泄漏的开源类库。你可以在的bug包中轻松检测内存泄漏。
以下就是很简单的3个步骤:
1.在项目中的build.gradle文件添加:
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
}
2.在Application中添加:
public class App extends Application {
private RefWatcher refWatcher;
@Override
public void onCreate() {
super.onCreate();
refWatcher=LeakCanary.install(this);
}
public static RefWatcher getRefWatcher(Context context){
App app = (App)context.getApplicationContext();
return app.refWatcher;
}
} 3.在你要检测的地方用RefWatcher观察这个对象
RefWatcher refWatcher = App.getRefWatcher(this);
refWatcher.watch(this);
例子:
public static Singleton getSingleton(Context context) {
if (singleton == null) {
singleton = new Singleton(context);
}
return singleton;
}
让这个静态的单例持有activity的引用。并且把这个acitivy finish掉。 没过一会儿,就会弹出一个消息出来。 可以准确的锁定为这个Activity的单例出现了泄漏。