(一)释放对象的引用,误将一个本来生命周期短的对象存放到一个生命周期相对较长的对象中,也称“对象游离“。隐蔽的内部类(Anonymous Inner Class):

mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

....

}

};

相当于:

class MyHandler implements Handler {

....

}

mHandler = new MyHandler();

类似的还有Listener,Observer,Receiver等。
    由于内部类隐含拥有一个外部类对象的引用,所以千万要注意内部类instance的声明周期。
    最好不要将一个内部类的instance暴漏出去,除非使用者采用weak reference引用内部类的instance。例如,一些Handler,Listener在做为返回值暴漏出去时,千万注意使用weak reference。
    注意:一些系统提供的类偷偷地将自己暴漏出去了,如FileObserver,会将自己暴漏到自己内部开的线程去,不过还好它使用的是weak reference。但是过分的是BroadcastReceiver,一旦我们使用Context的registerReceiver 之后,系统( ActivityManagerNative )就会有一个它的强引用,除非我们显式调用unregisterReceiver。

结论:任何提供了开关函数的类,都必须保证显式地调用它们的开关函数。

(二) 构造Adapter时,没有使用缓存的 convertView,从而造成系统创建了大量的view而没有来得及回收。

public View getView(int position, View convertView, ViewGroup parent)

(三)对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null。资源性对象,比如(Cursor等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。它们的缓冲不仅存在于java虚拟机内,还存在于java虚拟机外。如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄露。

(四)都是线程惹的祸

由于线程的执行时间是未知的,所以线程所持有的外部对象,一般要使用weak reference,除非你肯定它们的生命周期。

另外,向其它线程post Runnable或者send Message时也需要注意Runnalbe内部使用的变量和Message中的内容。

(五)AsyncTask-隐藏的故事

Asynctask使用了一个静态的ThreadPoolExecutor,有三个参数是系统固定的:

CORE_POOL_SIZE:5

MAXIMUM_POOL_SIZE:128

QUEUE_CAPACITY: 10

当一个AsyncTask被execute之后:

1.如果线程池中线程数目小于CORE_POOL_SIZE ,就直接开线程;

2.如果队列不满,就被加入队列中;

3.如果队列已满,就直接开线程执行;

4.如果线程池中线程数目大于MAXIMUM_POOL_SIZE,就会Exception。

Tricky的地方在于AsncTask的Cancel操作。

1.不一定都能成功,例如while(true){}就无法被cancel;

2.如果AsyncTask还在Queue中,那么cancel操作并不会将它从Queue中remove,而仅仅是设置了flag,最终当它被thread执行时,判断该flag,如果false,就不会执行doBackground的代码。

悲剧剧情:你在队列中,正在执行的几个哥们都block了,你就一直呆着吧。

(六)Bitmap-不得不说的故事

Bitmaps in Android are created innative memory, not on the VM heap, so the actual Bitmap object on the VM heapis very small as it doesn't contain any actual bitmap data.

一般情况下,我们都是按需索图,没必要把原始图片都搞进来,所以我们可以先查询原始图片大小,在做scale:

1. 查询原始图片大小,通过BitmapFactory.Options中的属性inJustDecodeBounds来做,If set to true, the decoder will return null (nobitmap), but the out... fields will still be set, allowing the caller to querythe bitmap without having to llocate the memory for its pixels.

2. 然后计算出一个scale的值,通过BitmapFactory.Options中的属性inSampleSize进行缩放。

Bitmap bitmap;

float imagew = 300;  // 目标大小

float imageh = 300;  // 目标大小

BitmapFactory.Options bitmapFactoryOptions = new BitmapFactory.Options();

bitmapFactoryOptions.inJustDecodeBounds = true;

bitmap = BitmapFactory.decodeFile(imageFile, bitmapFactoryOptions);

int yRatio = (int)Math.ceil(bitmapFactoryOptions.outHeight/imageh);

int xRatio = (int)Math.ceil(bitmapFactoryOptions.outWidth/imagew);

if (yRatio > 1 || xRatio > 1){

if (yRatio > xRatio) {

bitmapFactoryOptions.inSampleSize = yRatio;

} else {

bitmapFactoryOptions.inSampleSize = xRatio;

}

} else{

// inSampleSize = 1

}

bitmapFactoryOptions.inJustDecodeBounds = false;

bitmap = BitmapFactory.decodeFile(imageFile, bitmapFactoryOptions);

myImageView.setImageBitmap(bitmap);

    Bitmap-recycle有用吗?以下是官方源代码的注释:

Free the native object associated with this bitmap, and clearthe reference to the pixel data.

This will not free the pixel data synchronously;

it simply allows it to be garbagecollected if there are no other references. The bitmap is marked as "dead", meaning it willthrow an exception ifgetPixels() or setPixels() is called, and will draw nothing. This operation cannot be reversed, so it should only becalled if you are sure there are no further uses for the bitmap.

​    ​This is an advanced call,and normally need not be called, since the normal GC processwill free up this memory when there are no more references to this bitmap.

(七)substring的恶梦

​    ​public String substring(int beginIndex, int endIndex) {

​    ​return new String(offset + beginIndex,

endIndex - beginIndex,

value);

​    ​}

​    ​String(int offset, int count, char value[]) {

​    ​    ​ this.value = value;

​    ​    ​ this.offset = offset;

​    ​    ​ this.count = count;

​    ​}

​    ​也就是说即使你只想用其中的某几个字节,Java也自动把原始String的整个内容帮你保存下来了。

​    ​ArrayList<String> oomStringList = new ArrayList<String>(1024);

​    ​for (int i=0; i<32*1024; i++) {

​    ​String srcString = new String(new char[1024]);

​    ​String dstString = srcString.substring(0,1);

​    ​oomStringList .add(dstString);

​    ​​}

refrence:http://blog.csdn.net/edisonlg/article/details/7082063

Android内存泄露的原因的更多相关文章

  1. (转)专项:Android 内存泄露实践分析

    今天看到一篇关于Android 内存泄露实践分析的文章,感觉不错,讲的还算详细,mark到这里. 原文发表于:Testerhome: 作者:ycwdaaaa ;  原文链接:https://teste ...

  2. [转]深入Android内存泄露

    深入内存泄露 Android应用的内存泄露,其实就是java虚拟机的堆内存泄漏. 当然,当应用有ndk,jni时,没有及时free,本地堆也会出现内存泄漏. 本文只是针对JVM内存泄漏应用,进行阐述分 ...

  3. Java内存泄露的原因

    Java内存泄露的原因 1.静态集合类像HashMap.Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,所有的对象Object也不能被释放,因为他们也将一直被Vector ...

  4. 深入研究EF Core AddDbContext 引起的内存泄露的原因

    前两天逛园子,看到 @Jeffcky 发的这篇文章<EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下>. 一开始只是粗略的扫了一遍没仔细看,只是觉得是多次 ...

  5. 牛客网Java刷题知识点之内存溢出和内存泄漏的概念、区别、内存泄露产生原因、内存溢出产生原因、内存泄露解决方案、内存溢出解决方案

    不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑          ...

  6. android内存泄露调试,Heap,MAT

    三.内存监测工具 DDMS --> Heap 无论怎么小心,想完全避免bad code是不可能的,此时就需要一些工具来帮助我们检查代码中是否存在会造成内存泄漏的地方.Android tools中 ...

  7. android 内存泄露之jni local reference table overflow (max=512)

    在android项目中要实现一个需求 为了性能的要求只能用c代码来实现功能. 这样就牺牲了java跨平台性. 通过加载.so的方式,把用c实现的模块集成到app中. android提供jni层,作为一 ...

  8. Android内存泄露---检测工具篇

    内存使用是程序开发无法回避的一个问题.如果我们毫不在意肆意使用,总有一天会为此还账,且痛不欲生...所以应当防患于未然,把内存使用细化到平时的每一行代码中. 内存使用概念较大,本篇先讲对已有app如何 ...

  9. JVM内存管理概述与android内存泄露分析

    一.内存划分 将内存划分为六大部分,分别是PC寄存器.JAVA虚拟机栈.JAVA堆.方法区.运行时常量池以及本地方法栈. 1.PC寄存器(线程独有):全称是程序计数寄存器,它记载着每一个线程当前运行的 ...

随机推荐

  1. [转载]AI教师正来势汹汹,教师饭碗堪优

    (原文标题:开门,机器人老师来了) 一. 开门,机器人老师到了 国庆几天,河南刚刚上演一幕新科技的大戏: 计算机和人展开了为期四天的人机大战.这一次,对垒的双方不再是李世乭和阿尔法狗,而是教师和人工智 ...

  2. MySQL5.7以上Zip版官方安装文档(选译)

    前言 在windows上安装Zip版MySQL(选译) 学习mysql的朋友们会发现5.7+版本的mysql变得比以前难安装了许多(当然我们可以选择installer版本,但是这样总感觉对学习mysq ...

  3. Thrift总结(三)Thrift框架

    1.数据类型 基本类型: bool:布尔值,true 或 false,对应 Java 的 boolean byte:8 位有符号整数,对应 Java 的 byte i16:16 位有符号整数,对应 J ...

  4. JavaScript责任链模式

    介绍 责任链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理 ...

  5. iOS开发中使用文字图标iconfont

    在iOS的开发中,各种图标的使用是不可避免的,如果把全部图标做成图片放在项目中,那么随着项目的逐渐庞大起来,图片所占的地方就会越来越大,安装包也就随之变大了,如果图标需要根据不同的场景改变使用不同的颜 ...

  6. USACO奶牛博览会(DP)

    Description 奶牛想证明他们是聪明而风趣的.为此,贝西筹备了一个奶牛博览会,她已经对N头奶牛进行了面试,确定了每头奶牛的智商和情商. 贝西有权选择让哪些奶牛参加展览.由于负的智商或情商会造成 ...

  7. [CF] Final Exam Arrangement

    问题链接:http://www.bnuoj.com/v3/contest_show.php?cid=4329#problem/F   问题大意:         就是有1--N们课程,每一个课程都有一 ...

  8. Vue源码后记-更多options参数(1)

    我是这样计划的,写完这个还写一篇数据变动时,VNode是如何更新的,顺便初探一下diff算法. 至于vue-router.vuex等插件源码,容我缓一波好吧,vue看的有点伤. 其实在之前讲其余内置指 ...

  9. 读书笔记-你不知道的JS上-对象

    好想要对象··· 函数的调用位置不同会造成this绑定对象不同.但是对象到底是什么,为什么要绑定他们呢?(可以可以,我也不太懂) 语法 对象声明有两个形式: 1.字面量 => var obj = ...

  10. 纯js实现DIV拖拽

    写代码的时候遇到需要对绝对布局的div进行拖拽的功能,起初为了省事直接在网上扒拉了一番,看到大神张鑫旭的一篇文章<JavaScript实现最简单的拖拽效果>,便直接拿来使用(膜拜大神).但 ...