正确的姿势看待内存泄漏

前言
内存泄漏是在平时开发与面试中都比较常见的问题,好记性不如烂笔头。今日来有模样的总结一下(这次排版很用心的!!~)~

基础巩固

内存泄漏(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的单例出现了泄漏。

正确的姿势看待内存泄漏_第1张图片

正确的姿势看待内存泄漏_第2张图片

参考链接:利用 LeakCanary 来检查 Android 内存泄漏
github-leakcanary

你可能感兴趣的:(Android)