关于android内存泄漏的研究
博客建了几个月,都没有去写,一是因为当时换工作,然后又是新入职(你懂的,好好表现),比较忙;二是也因为自己没有写博客的习惯了。现在还算是比较稳定了,加上这个迭代基本也快结束了,有点时间来写写博客。好了,废话少说,下面进入正题,关于android内存泄漏的研究:
最近参与公司项目的迭代,发现这个几百万用户量的项目经过这么多的迭代了,还是一直存在严重的内存泄漏的问题,这个其实刚入职的时候就发现了,但是一直没敢说。现在也算是老员工了,这个迭代我提了出来,正好我的迭代开发工作也基本完成了,于是就是我去查这个问题,开始做的时候我才发现,给自己出了个难题,七,八万行的代码,很多的模块,很多的代码我都没接触过。没办法,只能硬着头皮来了。
android内存泄漏,其实泄漏几个String,泄漏几个普通对象,对用户体验没什么影响,主要问题在于泄漏了跟界面有关的东西,如View,Activity,PopupWidow,和Dialog,和Bitmap。泄漏,不只是说反复进入内存是不是一直增大,而且当你的这些界面关闭时,它所占用的空间会不会被释放掉。我们的项目有100多个PopupWindow,Dialog,和自定义View,十几个Activity,显然先查Activity是明智的,而且Activity的严重程度也比较高,于是找了个最简单的Activity开始查。
像数据库游标用完关闭,以及文件读取关闭,和全局Bitmap用完释放,这类的这里就不详细说了。
①像这些界面类,释放不掉,原因肯定是它自己的实例被传来传去,最后传到一个静态全局变量中,导致其一直释放不了(因为静态变量一直不释放)。或者是界面类的全局变量有引用到它自己,然这个变量可能又被其他的静态变量中,一直被引用着,没有释放掉。
建议:在要用到Context的时候,尽量传Application而不是Activity实例(有一些情况没办法,用完要做好手动释放)。
在这些界面类中,如果用到了静态变量引用到这些界面类本身,界面关闭的时候要手动释放掉。
如果是加入了ArrayList等集合中,那么界面退出时,要把它从集合中移除。(这个问题大了,不只是退出没有释放的问题,而是每一次操作都会使你的程序的内存增大,很快就会内存溢出)
②关于WebView使用,内存泄漏的问题。
WebView会占很大的空间,而且用普通的在xml布局中写WebView的方法,WebView并不会释放(查了资料,发现是android的bug),于是我们要动态加载它,可以把它放到一个ViewGroup中,在布局中加一个ViewGroup(RelativeLayout,FrameLayout都可以,其他的每测)在代码中new WebView(这里要传application,不要传Activity),然后把webview加入到ViewGroup中就可以。但是在界面关闭的时候记得释放掉:
viewGroup.removeAllViews(); webview.destroy(); webview = null ; |
就可以使其释放掉了。
关于内存泄漏查找工具,用的Memory Analyzer Tool,可能是我不太会用,感觉只是对那种每一次执行操作内存都会增大的情况有用,它就只帮我解决了一个这种问题,情况是我在每一次切换账户时,内存都会增大一些,于是我就不断的切换,然后用Memory Analyzer Tool去查看,一眼就找到了那个特别大的类,然后看了下代码,发现一直在往一个List里面加东西,没有移除。
这是我在我们的项目中发现的内存泄漏的相关问题,基本上把内存问题解决了,不过还是有一些泄漏,有的地方是找不到,有的地方是改动太大,现在不能动。不过问题不大,把所有界面跑一遍,在G1上泄漏了0点几兆,不会引起内存溢出。第①个看似简单,其实是最难找的,尤其是在特别大的项目中,它们隐藏的会特别深,所以我们在写代码的时候一定要去考虑的内存泄漏的情况,不然以后再查找起来,要浪费掉好几倍的时间。
如果还有其他的内存泄漏的情况或者有什么好的建议,希望大家补充,共同探讨,共同进步。