Android性能优化待读内存泄露

Android内存优化(二):一分钟发现内存泄漏

2017-03-15  本文已影响385人  C6C

在上一篇文章Android内存优化(一):Java内存区域中已经大体上介绍了Java中的内存分布情况,这一篇主要讲一下内存泄漏的产生原因、内存泄漏的危害、内存泄漏一键分析与定位、以及代码中常见的内存泄漏。

1内存泄漏的产生原因

前方高能,18岁以下请避让!!!
惊天大咪咪:内存泄漏产生的原因是对象占着茅坑不拉屎!!!
有必要讲一下Android中的垃圾收集是怎么进行的,Android中使用标记-清除(Mark-Sweep)算法进行垃圾回收(garbage collection,简称GC),就是按照正常套路来说,在坑位(内存)不够的情况下,垃圾收集器会遍历全部对象,看哪些对象是可以被回收掉腾出内存的,这个过程称为Mark(标记),Mark的时候要求除了垃圾收集线程之外,其它的线程都停止,这种吊炸天的现象在垃圾收集算法中称为Stop The World,世界围着他转,这就造成了我们的程序会卡顿,但是一般情况下这个时间就几十毫秒,我根本就感受不到好吗。Mark完之后,就是释放内存空间啦,这个过程称为Sweep(清除)。

这一切看起来很美好,但是就是有内存泄漏发生,所以得提一下,不是所有的对象都是特仑苏,阿呸,不是所有的对象都能被回收的,比如下面的傲娇贱货。

2内存泄漏的可能会造成的创伤

如果不是利用工具去找的话,一般情况下内存泄漏是比较难发现的,因为Java中不会报内存泄漏这种异常,所以在轻微的内存泄漏表面上看是跟正常情况下没有区别的。

3内存泄漏的发现

内存泄漏的分析的话,必须使用工具才行,庆幸的是,各路大神已经给我们提供了很多强大的内存分析工具,我这里只会讲最方便的。这里提供几个套餐供选择

3.1 套餐一:Studio自带Heap Viewer

想不想知道你的应用到底有没有内存泄漏呢?说真,就一分钟的事。

3.2套餐二:Heap Viewer + MAT

是啊,发现有内存泄漏了,然而还有其它的选择,这里就必须使用到其它的工具进行辅助了。


MAT(Memory Analyzer)内存分析工具,这个工具的使用我只简单讲一下,因为我一般不用,不要问为什么,因为用起来比较麻烦一些。

3.3套餐三:Leakcanary

square的开源内存泄漏分析框架,好用得不得了,配置很简单

dependencies {
        debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
        releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
        testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
 }
public class ExampleApplication extends Application {

  @Override public void onCreate() {
    super.onCreate();
    if (LeakCanary.isInAnalyzerProcess(this)) {
      // This process is dedicated to LeakCanary for heap analysis.
      // You should not init your app in this process.
      return;
    }
    LeakCanary.install(this);
    // Normal app init code...
  }
}

注:到这里3个套餐已经讲完了,关于MAT这个套餐我只是讲一下基本的使用,其实已经够用了,怎么说呢,用起来比较麻烦,所以我自己本身也很少用,我就按自己的使用对比一下三者。
套餐三>套餐一>套餐二
1.套餐三使用最方便,一劳永逸,解析hprof的速度有点慢,但是因为后台自动解析,所以基本上没多大关系;
2.套餐一使用最快,切换一下页面分分钟就知道有没有内存泄漏,但是需要你每一次都要手动操作;
3.套餐三最麻烦,耗时耗力,但是自动分析工具并不能保证找出所有的内存泄漏,这个时候就需要通过MAT辅助分析了。

4代码里头内存泄漏的常见原因

代码中内存泄漏大多数产生的原因是不遵循activity的生命周期。

/**
  * 单例模式
 */
public class SingletonClass{
    private static SingletonClass instance;
    private Context context;
    public static SingletonClass getInstance(Context context){
            synchronized(SingletonClass.class){
                if(instance==null){
                    instance=new SingletonClass(Context context);
                }
            }
        return instance;
    }
    private SingletonClass(Context context){
       this.context = context; //传入activity的context就会造成内存泄露咯
    }
}
private static View view;
view = findViewById(R.id.sv_button);
        private static InnerClass inner = new InnerClass();
        class InnerClass {
        }
new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                while(true);
            }
        }.execute();
new Handler() {
         @Override
         public void handleMessage(Message message) {
                super.handleMessage(message);
            }
        }.postDelayed(new Runnable() {
            @Override public void run() {
                while(true);
            }
        }, 1000);
new Thread() {
            @Override public void run() {
                while(true);
            }
        }.start();

可以了,造成内存泄露还有很多原因,这就靠慢慢跳坑了,生活太艰难。再话痨一下,“千丈之堤,以蝼蚁之穴溃;百尺之室,以突隙之烟焚。”,所以我推荐套餐三Leakcanary,让你的整个开发过程伴随着内存泄露的监控。

上一篇下一篇

猜你喜欢

热点阅读