Android性能优化篇——内存泄漏和OOM

原创 2018年04月16日 00:26:29
Android性能优化篇——内存泄漏和OOM
老规矩,在讲解以前先提出问题:
(1)什么是内存泄漏?什么是内存溢出
(2)如何检测app的最大堆内存?
(3)如何测量内存泄漏?
(4)如何避免内存泄漏?
好了,直接进入主题。

一、内存泄漏和内存溢出
        1、内存泄漏
            内存泄漏是指某些对象本应该被GC回收,但是由于他们的引用被其他对象持有而导致GC回收失败,从而无法回收占用的内存,结果导致这些无用对象仍然占据着堆中的内存空间,成为内存泄漏。
            内存泄露的危害:
        (1)过多的内存泄露会导致内存被过多占用,容易发生OOM
        (2)内存泄露可能给会导致内存不足,然后频发发生GC,可能会导致UI卡顿,线程停止等问题。
        2、内存溢出
            Android为每个进程会设置一个内存的阈值,如果超过这个阈值则会发生内存溢出,程序就会崩溃。
            内存溢出的危害:
            程序可能会崩溃,为什么是可能,因为内存溢出可以被try——catch。

二、app的堆内存阈值
        这里的阈值与设备有关系,所以不是一个固定的数值。
        通常我们可以通过两个参数来查看我们堆内存阈值:
        heapsize  设备分给堆内存的最大堆内存
        maxheapsize    用于特殊情况下(设置了清单文件中的application的属性largeHeap = true)时才有的最大堆内存,一般为heapsize的2~3倍,设置后则最大堆内存为maxheapsize、
        那么如何获取这两个值:
ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int heapSize = manager.getMemoryClass();
int maxHeapSize = manager.getLargeMemoryClass();  // manafest.xml   android:largeHeap="true"

三、如何检测内存泄露
        可以通过As的profiler+facebook的开源库 leakcanary来分析
 
二、常见的内存泄露场景
        1、非静态内部类的内存泄露
             原因:
              非静态内部类会持有外部类的this引用,因此可以访问外部类的静态和非静态变量。如果内部类的生命周期超过外部类,则会导致外部类无法被及时回收
             解决方法:
               创建static静态变量,并通过弱引用WeakReference来引用外部资源
        2、单例模式持有Activity的引用
               原因:
                在单例模式中,如果传入Activity的Context,那么在Activity退出时,由于Context持有Activity的引用,因此导致Activity不会被回收
              解决方法:
                 改为Application的Context
        3、Handler造成的内存泄露
                    我们常见的写法是:

 private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //...
        }
    };
也就是我们前面提高的非静态内部类,持有外部类的this引用,那么假如说消息队列中还有没有处理完的Message,而Message又有一个属性变量Handler,也就是持有当前Handler对象的引用,而Handler又持有当前Activity的引用,这样就可能导致Activity已经结束,但是由于引用被持有而无法释放。因此我们改进的方法主要是两方面,第一,Acitvity结束时调用 mHandler.removeCallbacksAndMessages(null);清空消息队列中的消息和Runnable。第二,改为static内部类,不持有外部类的this引用。
改为如下:
    private static class MyHandler extends Handler {
        private WeakReference<Context> reference;
        public MyHandler(Context context) {
            reference = new WeakReference<>(context);
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = (MainActivity) reference.get();
            if(activity != null){
                activity.mTextView.setText("");
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }

4、线程造成的内存泄露
        直接使用AsyncTask和Thread,相当于使用一个非静态内部类,因此会持有当前Activity的引用this。
     
static class MyAsyncTask extends AsyncTask<Void, Void, Void> {
        private WeakReference<Context> weakReference;
  
        public MyAsyncTask(Context context) {
            weakReference = new WeakReference<>(context);
        }
  
        @Override
        protected Void doInBackground(Void... params) {
            SystemClock.sleep(10000);
            return null;
        }
  
        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            MainActivity activity = (MainActivity) weakReference.get();
            if (activity != null) {
                //...
            }
        }
    }
    static class MyRunnable implements Runnable{
        @Override
        public void run() {
            SystemClock.sleep(10000);
        }
    }
//——————
做法是转化为静态内部了类
5、资源未关闭导致
      比如数据库,文件,广播,Stream,Bitmap等
               



版权声明:本文为博主原创文章,转载请说明出处 https://blog.csdn.net/ckq5254/article/details/79955422

Android 内存泄漏及优化防止OOM——进阶必看篇

前言:内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题。内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC...
  • csdn_aiyang
  • csdn_aiyang
  • 2017-04-01 12:07:27
  • 1343

Android内存泄漏解决方案(OOM)

为什么会有内存泄漏?一个不会被使用的对象,因为另一个正在使用的对象持有该对象的引用,导致它不能正常被回收,而停留在堆内存中,内存泄漏就产生了Android系统为每个应用分配的内存是有限的,内存泄漏会使...
  • imuhao
  • imuhao
  • 2016-06-16 19:25:04
  • 5713

Android 性能优化之使用MAT分析内存泄露问题

我们平常在开发Android应用程序的时候,稍有不慎就有可能产生OOM,虽然JAVA有垃圾回收机,但也不能杜绝内存泄露,内存溢出等问题,随着科技的进步,移动设备的内存也越来越大了,但由于Android...
  • xiaanming
  • xiaanming
  • 2015-01-09 08:50:47
  • 34102

【Android性能优化】内存泄露和内存溢出(OOM)的引发原因及优化方案

一、内存泄露 垃圾回收器无法回收原本应该被回收的对象,这个对象就引发了内存泄露。 内存泄露的危害: (1)过多的内存泄露最终会导致内存溢出(OOM) (2)内存泄露导致可用内存不足,会触发频繁GC,...
  • mxm691292118
  • mxm691292118
  • 2016-03-30 22:21:29
  • 15596

OOM,内存泄漏检测工具:LeakCanary

尊重原创作者,转载请注明出处: 千里之堤,毁于蚁穴qiān lǐ zhī dī,huǐ yú yǐ xué。释义:一个小小的蚂蚁洞,可以使千里长堤毁于一旦。 比喻小事不注意会造成大乱子。出处:《韩非...
  • u013134391
  • u013134391
  • 2016-06-05 13:40:05
  • 1156

Android 内存泄漏和OOM分析(二)

OOM 内存泄漏 处理方法
  • zhcswlp0625
  • zhcswlp0625
  • 2017-01-15 18:24:26
  • 4177

Android中内存泄露与如何有效避免OOM总结

Android系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会导致应用所需要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash。内存泄露的危害:只有...
  • gjnm820
  • gjnm820
  • 2016-06-03 15:09:49
  • 4529

Android OOM:内存管理分析和内存泄露原因总结

一、Android进程的内存管理分析1. 进程的地址空间在32位操作系统中,进程的地址空间为0到4GB,示意图如下: 这里主要说明一下Stack和Heap: Stack空间:(进栈和出栈)由操作...
  • u014136472
  • u014136472
  • 2015-11-05 14:30:44
  • 2257

Android 性能优化之内存泄漏检测以及内存优化(上)

在Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的,程序员不需要通过调用函数来释放内存,但也随之带来了内存泄漏的可能...
  • zhao_zepeng
  • zhao_zepeng
  • 2017-04-10 20:49:13
  • 4777

Android性能优化之常见内存泄漏和优化方案

本文转载自http://www.jianshu.com/p/ab4a7e353076 感谢原作者xiaoyanger 如果一个无用对象(不需要再使用的对象)仍然被其他对象持有引用,造成该对...
  • zlgzh
  • zlgzh
  • 2017-04-14 13:38:00
  • 2231
收藏助手
不良信息举报
您举报文章:Android性能优化篇——内存泄漏和OOM
举报原因:
原因补充:

(最多只允许输入30个字)