Android内存泄漏
今年搞了一个图片浏览类型的项目,背影美女。美女的吸引力果然是永恒的,上线之后还颇受欢迎。但有个问题很头疼,就是内存泄漏导致的大量OOM崩溃,根据友盟统计,出现次数/启动次数达到了10%以上。
最初的想法,是这样明显的内存问题,可能跟图片没有及时释放有关。找来找去,发现sdk本身就提供了相关的功能,创建bitmap的时候,bitmapoption里面有inPurgeable的属性。设置为true的情况下,该bitmap会在系统需要时被回收。于是把所有创建bitmap的地方都加了设置。结果略有成效,但效果甚微。
于是继续去找谷歌和度娘,得到的信息很明确,最常见的情况,是context没有释放,而原因很多,总之是有引用存在。于是用MAT进行分析,但郁闷的是,MAT提供的Leak suspects过于底层,比如一大堆String之类。究其原因,想必是按照占用内存大小来分析,context虽然是罪魁祸首,直接占有的内存却不是很多,于是没有被优先列出来。MAT之前没有用过,一时还真没有办法。
无奈之下,只好去分析代码。一看之下,还真发现些问题,比如有循环引用的地方,A的成员保存了某view的引用,view又设置了A为tag。于是缠缠绵绵,谁也不释放谁了。不幸的是,view里面都有context引用,于是整个activity都不能释放。修改了这些明显的问题,效果仍然很差。只好先放下它,干别的去了。好在美女的引力确实够大,即使经常崩溃,也还有不少人坚持使用,偶很感动。
有个成语叫如鲠在喉,这么恶心的问题不解决,实在让人不爽。一个偶然的机会,看到有人也用MAT分析解决了android的内存泄漏,于是信心又生,继续研究MAT。发现抛开Leak suspects分析,直接看overview信息,里面的Histogram可以列出所有类的对象数量。从中搜索某Activity,果然在多次启动之后,它的对象数一直在上升,之前的没有释放。有了这些就好办了,右键菜单list objects列出所有对象,在对象上再右键,path to GC Roots,exclude soft/weak reference。就可以看到引用。然后对症下药就好了。
最后发现,导致context无法释放的原因不止一个。一是图片异步加载的线程中有imageview的引用;二是退出时的toast提示,程序退出时提示还没有消失,它所保持的context引用就不能释放;三是友盟的统计方法,不过最新版本的友盟已经修改了这个bug,不再使用强引用了。这些都修改之后,OOM崩溃减少到原来的20%左右。通过对heap的观察,泄漏问题不存在了,剩下的OOM,可能是其他原因,需要继续研究了。
浙公网安备 33010602011771号