中秋一次历时10小时的内存泄露修复

0、序

最近新版本上线,随着用户增多,发现5.0上的OOM类型的错误异常的多,但是4.4上除了一些低端机型都没有出现同样的问题,作为一个开发人员怎么能不找出原因呢?!!


1、工具

对于内存泄露这种问题,当然要祭出LeakCanary这种查内存泄露的神器啦。

使用的方式也很简单,用maven就行。使用方法如下,在app的build.gradle下面加入你要用的版本。因为自己项目正式发布时不会用这个,所以只用了debug版本的。

 dependencies {
   debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
   releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
 }
然后在你的自定义的Application下面加入
public class ExampleApplication extends Application {

  @Override public void onCreate() {
    super.onCreate();
    LeakCanary.install(this);
  }
}
ok,搞定。但是如果你还想要自己定义监控的页面或者变量,可以参考 https://github.com/square/leakcanary#how-do-i-use-it
由于当时我的项目中不清楚到底什么地方泄露了,所以只做了前面的步骤。

2、思考
    由于自己做的是动态图片应用,第一反应就是图片没释放。于是在动图播放控件detach的时候,全部置为null,但是结果还是内存泄露。但是奇怪的是5.0以下的机型不会内存泄露,但是5.0及以上的内存就死死的释放不了。当时的另一个想法是系统内存泄露了,可参考链接 http://www.ithome.com/html/android/120575.htm
虽然这么想,但是我觉得作为一个程序猿应该先想到可能还是自己的代码有问题,而不能盲目的猜测。

于是用LeakCanary一查,发现是动图播放控件没有释放,一环接一环的影响了Activity的释放,最终内存泄露了。但是一看自己的代码,不管在detach或者切换时都已经做了释放,不可能出现未释放的情况。

接下去,我就在recyclerView里面找原因,觉得会不会是recyclerView并没有detach掉列表项,因为之前找到了很多个recyclerView的bug,于是乎就打印log查找是否detach,但是发现每一项都被detach了。同时我注意到另一个问题,当我只是慢速滑动的时候,LeakCanary并不显示内存泄露,而是在我快速滑动的时候,LeakCanary就显示内存泄露了。我想会不会是快速滑动导致detach失效呢?但并不是这样的,在快速滑动过程中,每一项都有被bind到,也同时会被detach。

由于之后没有头绪,甚至就试着关闭快速滑动。阳台上走了一圈,突然灵感迸发,如果是内存泄露,会不会是线程没有停止,于是就查看lib,然后打印日志,果然在快速滑动下线程并没有被关闭,而是一直在输出log日志。因为在线程中持有了一个Handler对象,Handler对象又被控件所持有,结果就恶性循环导致内存没法释放。但是改成WeakReference的Handler,发现也存在泄露问题,说明这个线程在其他地方被启动了。查找了app module下所有启动的地方,发现并没有不符合规范的地方,后来又去lib下面查找,才发现在图片下载完成之后竟然直接就启动线程播放了。。。。。于是把线程开始全部改成代码控制。


3、结论
不要在一个线程结束后有紧接着调用一个死循环的线程,除非你有特定的条件去触发线程停止,否则最好还是在可控的范围内调用线程,毕竟这东西是不可控的,就算你退出程序,还是会运行。

Over


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值