一:首先我们来区分一下内存泄漏和内存溢出两个概念:
1.内存溢出:(out of memory)是指程序在申请内存的时候,没有足够的内存空间供其使用造成OOM,主要是JVM内存过小,程序不严密,产生了过多的垃圾。
主要原因有:有占有内存过多,内存泄漏等。
a.内存加载的数量过去庞大,如一次从数据库中取出过多的数据。最好设置分页,优化查询语句
c.代码中存在设计不合理的递归、死循环等产生过多的重复对象。注意代码质量,避免递归、循环过程中产生大量垃圾。
d.参数内存值设定过小。如定义了int的长度确赋Long长度的值
f. 使用了“非字面量字符串进行了+”的操作。因为String类的内容是不可变得,每次运行+操作都会生成新的对象,例如
String s1 = “hello”;
String s2 = “world”;
String s3 = “!”;
┊
String str = s1 + s2 + s3 ···这样很容易造成内存溢出,应用StringBuffer或StringBuilder更优。
Android中内存溢出的具体表现:
一:大量位图的加载:Bitmap是相当耗内存的,如果一次性加载大量的位图,那么程序可用内存就会瞬间增长造成OOM,所以Bitmap在不使用的情况下用recycle释放内存。
二:查询数据库没有关闭游标:在我们大量操作数据库的情况下游标未关闭造成OOM的现象还是比较常见的,所以游标要及时调用close方法关闭。
三:构造Adapter时没有使用缓存的convertView,例如ListView中Item足够多,在没有使用convertView的情况下每次都会在getView()中去实例化一个Item,这样迟早造成OOM。
2.内存泄漏:(memory leak)是指程序在申请内存后,无法释放已经申请的内存空间;如果这些空间过大,造成的危害会很严重。
具体原因:
一:引用没释放造成内存泄漏,
a.如Android程序可能引用系统的Android程序对象(比如注册机制),如果这些注册没有被取消很容易造成垃圾不能及时回收。
b.集合中有对对象的引用,使用完后未清空。如数组、List、Map中存放的是对象的引用而不是对象,这些引用会让对应的对象不能被释放。个人理解(如list是一个长生命周期 然后他引用了一个实体对象,正常来说这个实体对象没用了就会被GC,但由于list占有这这个实体引用在哪里,就造成实体不能GC进而产生内存泄漏)
c.static使用过多,在类中的属性中使用static最好只用基本类型,如 static int i = 0;而不要引用资源消耗过多的实例,如Context等。
d.线程(内部类)使用不当,主要原因如线程是Activity的内部类,这些内部类在没有定义成static或没用WeakReference的情况下是是可以直接使用activity的引用的,这样在Activity推出的时候而内部类在执行长生命活动,造成Activity里面的内存不能释放,产生内存泄漏。主要处理方式是将其定义成static或者利用弱引用引用这个Activity。
二:资源对象没有关闭造成内存泄漏
a.资源性对象,如Cursor,File文件等,往往都用了缓冲,我们在不再需要使用的情况下应该及时关闭,以便它们的缓冲能及时回收内存。