Android中内存泄露与内存溢出

面试中经常会问到什么是内存泄露?什么又是内存溢出?
今天就来好好总结一下。

一、内存泄露 ( memory leak )

垃圾回收器无法回收原本应该被回收的对象,这个对象便引发了内存泄露。
内存泄露的危害:

(1)过多的内存泄露最终会导致内存溢出(OOM)
(2)内存泄露导致可用内存不足,会触发频繁GC,不管是Android2.2以前的单线程GC还是现在的CMS和G1,都有一部分的操作会导致用户线程停止(就是所谓的Stop the world),从而导致UI卡顿。

二、内存溢出(OOM-out of memory)

程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

Android为每个进程设置Dalvik Heap Size阈值,这个阈值在不同的设备上会因为RAM大小不同而各有差异。如果APP想要分配的内存超过这个阈值,就会发生OOM。

ActivityManager.getMemoryClass()可以查询当前APP的Heap Size阈值,单位是MB。

在3.x以前,Bitmap分配在Native heap中,而在4.x之后,Bitmap分配在Dalvik或ART的Java heap中。

Android 2.x系统,当dalvik allocated + native allocated + 新分配的大小 >= dalvik heap 最大值时候就会发生OOM,也就是说在2.x系统中,考虑native heap对每个进程的内存限制。

Android 4.x系统,废除了native的计数器,类似bitmap的分配改到dalvik的java heap中申请,只要allocated + 新分配的内存 >= dalvik heap 最大值的时候就会发生OOM(art运行环境的统计规则还是和dalvik保持一致),也就是说在4.x系统中,不考虑native heap对每个进程的内存限制,native heap只会收到本机总内存(包括RAM以及SWAP区或分页文件)的限制。

三、内存泄露的原因

比如当你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。

1.资源对象没关闭
如Cursor,File等资源。他们会在finalize中关闭,但这样效率太低。容易造成内存泄漏
SQLiteCurost,当数据量大的时候容易泄漏
2.使用Adapter时,没有使用系统缓存的converView
3.没有即时调用recycle()释放不再使用的bitmap
4.使用application的context来替代activity相关的context
不要让生命周期长于Activity的对象持有到Activity的引用
5.广播注册没取消造成内存泄露
6.Handler应该申明为静态对象, 并在其内部类中保存一个对外部类的弱引用。
7、Context持有导致内存泄漏
Activity Context被传递到其他实例中,这可能导致自身被引用而发生泄漏。
解决:对于大部分非必须使用Activity Context的情况(创建Dialog的Context必须是Activity Context),应该使用Application Context。
8、记得注销监听器
注册监听器的时候会add Listener,不要忘记在不需要的时候remove掉Listener。

内存泄露会引发内存溢出。
参考连接:http://blog.csdn.net/mxm691292118/article/details/51020023

你可能感兴趣的:(Android中内存泄露与内存溢出)