定义

内存泄漏也称作 “存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。
 
内存泄漏形象的比喻是 “操作系统可提供给所有进程的存储空间正在被某个进程榨干”,最终结果是程序运行时间越长,占用存储空间越来越多,最终用尽全部存储空间,整个系统崩溃。所以 “内存泄漏” 是从操作系统的角度来看的。这里的存储空间并不是指物理内存,而是指虚拟内存大小,这个虚拟内存大小取决于磁盘交换区设定的大小。由程序申请的一块内存,如果没有任何一个指针指向它,那么这块内存就泄漏了。
 
——来自《百度百科》

影响

成效

内存泄露实施后,项目的收获:

类型

技巧

类型 垃圾回收时间 生存时间
强引用 永远不会 JVM 停止运行时终止
软引用 内存不足时 内存不足时终止
弱引用 垃圾回收时 垃圾回收时终止
虚引用 垃圾回收时 垃圾回收时终止

Java 引用介绍(http://blog.csdn.net/mazhimazh/article/details/19752475
Java 四种引用由高到低依次为:强引用  >  软引用  >  弱引用  >  虚引用
表格说明

分析  

原理

根本原因

怎么解决

 实践分析

方案

实践(示例)

Bitmap 泄露

Bitmap 泄露一般会泄露较多内存,视图片大小、位图而定


@Override
  protected void onDestroy() {
      // TODO Auto-generated method stub
      super.onDestroy();
      recycleImageView(imgv_load_ad);
      }

  public static void recycleImageView(View view){
          if(view==null) return;
          if(view instanceof ImageView){
              Drawable drawable=((ImageView) view).getDrawable();
              if(drawable instanceof BitmapDrawable){
                  Bitmap bmp = ((BitmapDrawable)drawable).getBitmap();
                  if (bmp != null && !bmp.isRecycled()){
                      ((ImageView) view).setImageBitmap(null);
                      bmp.recycle();
                      bmp=null;
                  }
              }
          }
      }

IO 流未关闭

public static void copyFile(File source, File dest) {
          FileChannel inChannel = null;
          FileChannel outChannel = null;
          Log.i(TAG, "source path: " + source.getAbsolutePath());
          Log.i(TAG, "dest path: " + dest.getAbsolutePath());
          try {
              inChannel = new FileInputStream(source).getChannel();
              outChannel = new FileOutputStream(dest).getChannel();
              inChannel.transferTo(0, inChannel.size(), outChannel);
          } catch (IOException e) {
              e.printStackTrace();
          } finally {
              if (inChannel != null) {
                  try {
                      inChannel.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              if (outChannel != null) {
                  try {
                      outChannel.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
E/StrictMode: A resource was acquired at attached stack trace but never released. 
See java.io.Closeable for information on avoiding resource leaks.
java.lang.Throwable: Explicit termination method 'close' not called
    at dalvik.system.CloseGuard.open(CloseGuard.java:180)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:89)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
    at com.heyniu.lock.utils.FileUtil.copyFile(FileUtil.java:44)
    at com.heyniu.lock.db.BackupData.backupData(BackupData.java:89)
    at com.heyniu.lock.ui.HomeActivity$11.onClick(HomeActivity.java:675)
    at android.support.v7.app.AlertController$ButtonHandler.handleMessage(AlertController.java:157)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

单例模式泄露

静态变量持有 Context 实例泄露

-  public static void cancel(int TaskId) {
-         if(req != null && req.get() != null){
-           req.get().AsyncCancel(TaskId);
 -       }
    }
private static WeakReference<HttpRequest> req;public static void HttpUtilPost(Context context, int TaskId, String url, String requestBody,ArrayList<HttpHeader> Headers, RequestListener listener) {
        // TODO Auto-generated constructor stub
        req = new WeakReference<HttpRequest>(new HttpRequest(context, url, TaskId, requestBody, Headers, listener));
        req.get().post();
    }
private static HttpRequest req;public static void HttpUtilPost(Context context, int TaskId, String url, String requestBody,ArrayList<HttpHeader> Headers, RequestListener listener) {
        // TODO Auto-generated constructor stub
        req = new HttpRequest(context.getApplicationContext(), url, TaskId, requestBody, Headers, listener);
        req.post();
    }

image

服务未解绑注册泄露

Handler 泄露

异步线程泄露

后面

未完待续。。。
阿里云测移动质量中心(以下简称 MQC)是为广大企业客户和移动开发者提供真机测试服务的云平台,拥有大量热门机型,提供 7x24 全天候服务。

我们致力于提供专业、稳定、全面、高价值的自动化测试能力,以及简单易用的使用流程、贴心的技术服务,并且帮助客户以最低的成本、最高的效率发现 APP 中的各类隐患(APP 崩溃、各类兼容性问题、功能性问题、性能问题等),减少用户流失,提高 APP 质量和市场竞争力。

联系我们:
 网站地址:https://mqc.aliyun.com
 开发者交流旺旺群:335334143
 开发者交流 QQ 群:492028798
 客服邮箱:mqc_group@service.alibaba.com
更多精彩技术分享 欢迎关注 MQC 公众号  
17


↙↙↙阅读原文可查看相关链接,并与作者交流