如果需要动态分配一块内存,程序员需要负责这块内存的整个生命周期。从申请分配、到使用、再到最后的释放。程序员很容易由于疏忽而忘记释放内存,从而导致内存的泄露。
Java中对内存对象的访问,使用的是引用的方式。在Java代码中我们维护一个内存对象的引用变量,通过这个引用变量的值,我们可以访问到对应的内存地址中的内存对象空间。在Java程序中,这个引用变量本身既可以存放堆内存中,又可以放在代码栈的内存中(与基本数据类型相同)。GC线程会从代码栈中的引用变量开始跟踪,从而判定哪些内存是正在使用的。如果GC线程通过这种方式,无法跟踪到某一块堆内存,那么GC就认为这块内存将不再使用了(因为代码中已经无法访问这块内存了)。
可以多使用临时变量。或者通过设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。
第一,是在声明对象引用之前,明确内存对象的有效作用域
第二,在内存对象不再需要时,记得手动将其引用置空。
2,尽量不要使用static变量,因为static是全局的,GC不会回收。
3,避免集中创建对象尤其是大对象,JVM会突然需要大量内存,这样必然会触发GC优化系统内存环境
4, 不要在经常调用的方法中创建对象,尤其是不要再循环中创建对象
5, 当操作完数据库之后,及时关掉cursor。
6, 以构造ListView的BaseAdapter为例,在BaseAdapter中提供了方法getView(int position, View convertView, ViewGroup parent)来向ListView提供每一个item所需要的view对象。初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的view对象,同时ListView会将这些view对象缓存起来。当向上滚动ListView时,原先位于最上面的list item的view对象会被回收,然后被用来构造新出现的最下面的list item。这个构造过程就是由getView()方法完成的,getView()的第二个形参 View convertView就是被缓存起来的list item的view对象(初始化时缓存中没有view对象则convertView是null)。
由此可以看出,如果我们不去使用convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大
7, 如果有很多字符串需要处理,用StringBuffer而不用String。
8, 检查List,Map等集合对象是否有使用完后,未清除的问题。
9, 避免死循环或递归调用
10, 在registerReceiver之后及时调用unregisterReceiver
11, Bitmap对象不用的时候记得recycle()。
12, 如果在内存里面缓存大量图片或字符串,最好用软引用或弱引用
强:不会被gc收集
软:根据内存情况被gc收集
弱:过一段时间就会被收集
13,将图片压入内存得到bitmap之前先利用BitmapFactory.Options的inSampleSize的值得到压缩图片,这样会省内存。比如inSampleSize=2,图片将压缩为原图的1/2,占用内存也会变为1/2,而且这样的处理是在加载到内存之前进行的。这在处理很大图片时是必须的。
14, 尽量在程序中少使用对图片的放大或缩小或翻转.在对图片进行操作时占用的内存可能比图片本身要大一些。
15, 一个对象被多个对象引用,但是只释放了一处,也可能会导致这个对像不会被释放。
16, 一些长周期的对像引用了短周期的对象,但是这些短周期的对象可能只在很小的范围内使用