Java提供了垃圾回收这一强大的功能,但也蒙蔽了程序员的双眼,很难发现内存是否泄露,下面我们看看什么情况会发生内存泄露?
如下场景可能会发生内存泄露
- 类的静态变量持有大数据对象
- 静态变量长期维持到大数据对象的引用,阻止垃圾回收。
- 非静态内部类的静态实例
- 非静态内部类会维持一个到外部类实例的引用,如果非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。
- 资源对象未关闭
- 资源性对象如Cursor、File、Socket,应该在使用后及时关闭。未在finally中关闭,会导致异常情况下资源对象未被释放的隐患。
- 注册对象未反注册
- 未反注册会导致观察者列表里维持着对象的引用,阻止垃圾回收。
- Handler临时性内存泄露
- Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。
本人整理了下面一些方法来防止内存泄露
1、Listview的item泄露
这个是入门问题了,加入ViewHolder可以减少findViewById的时间,或者使用RecyclerView,来解决“滑动很卡”的问题。这个实质也是一个单例。
2、StringBuilder
尽量使用StringBuilder,而不用String来累加字符串,你现在还记得String,StringBuilder,StringBuffer的区别吗?
StringBuffer其实是给StringBuilder加了同步锁;其实你使用Log.d(TAG,”xx” + “yy”)这类写法后,编译器生成的代码已经自动帮你变成StringBuilder了
多用基本类型
使用int而不用Integer,较少的对象花销。在Android中使用sparseArrayMap取代HashMap就是把key变成了int,而一定程度上减小了内存占用。
3、Native代码不受GC控制
Native层面的代码不受到GC控制,又是长篇大论了,取决于C的水平。Malloc的内存一定要free,free后记得把指针置空,还有new 与delete的区别,一笔带过吧。
4、使用弱引用
使用弱引用可以防止一定程度的无意引用造成的泄露,比如在Handler中使用弱引用作为参数,当销毁的时候就有可能不会发生泄露