欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

记一次诡异的Bug修复——App自启动,bug修复app,开发者梦寐以求的应用常驻

来源: 开发者 投稿于  被查看 8069 次 评论:176

记一次诡异的Bug修复——App自启动,bug修复app,开发者梦寐以求的应用常驻


1、前言

在上一版本App临发版之前,QA和PM同学同时报了一个严重的Bug:App退出之后会自动重新启动,也就是用户关不了App。开发者梦寐以求的应用常驻就这么被莫名其妙的实现了!当然这是句玩笑,估计用户会直接了当卸载才是真的。

我们项目里确实也有应用保活的策略,但是并不流氓,更不会无厘头的在用户主动关闭App的时候重启。

2、分析

最初进行了两点分析:

  • RD在App退出的方法里加了重启的代码,自测使用却提交到了代码仓库;

  • App崩溃导致的重启,因为项目里有崩溃之后自动重启的逻辑;

但是查看代码之后否定了以上分析:

  • App退出的方法里没有被修改;

  • 确认应用没有崩溃,而且项目里也有崩溃保护策略,不会无限次、任意时间都可以重启。

而且在开发阶段其实发现过这个Bug,但是每当闲下来追踪的时候会发现Bug又不复现了。可以得出结论:这是一个非必现、场景复现的Bug。

3、解决

一筹莫展之际,我采用打Log的方式观察App的启动过程,没有发现启动的异常,但发现了启动页Activity的onDestroy()方法没有执行。大喜过望的我马上Dump了当前的堆栈信息,AndroidStudio打开之后按照包名的方式去查找启动类SplashActivity,发现应该被销毁的SplashActivity实例数量不为0。


应该被销毁的SplashActivity实例数量不为0
应该被销毁的SplashActivity实例数量不为0


继续深究,排查为什么SplashActivity实例还存在,此时就需要MAT上场大显身手:

3.1 使用Histogram功能检索SplashActivity的实例对象;


检索SplashActivity实例
检索SplashActivity实例


3.2 对着SplashActivity对象实例点击右键 -> List objects -> with incoming references 查看具体实例;


查看具体SplashActivity实例
查看具体SplashActivity实例


3.3 然后排除掉软引用的干扰;


注意左下角那个小圆圈
注意左下角那个小圆圈


至此:SplashActivity实例不被销毁的原因找到了:ShowAdInstance中持有了SplashActivity的引用,ShowAdInstance不被销毁,那么SplashActivity也无法被销毁。

那么ShowAdInstance为什么不被释放呢?ShowAdInstance中封装了广告页下载、展示的逻辑,持有了SplashActivity的引用,但是明明也是有注销的啊。反复查看代码逻辑最终定位到有一处判断漏调了注销的方法,导致SplashActivity对象没有被销毁,App杀掉进程之后由于SplashActivity的存在导致应用直接重启。

而上面也说到了:这是个场景复现的Bug,这个场景就是下载了开机闪屏图但是没有到显示时间。而这个场景出现的原因是开机闪屏图有预上线的策略。

至此,真相大白,果然在此处逻辑判断里加上了注销的代码之后App的退出又重启功能就不见了。

4、总结

4.1 思路

遇到这种诡异Bug的一个思路:猜测原因,快速验证;辅助Log,抓住一点持续突破。

4.2 其它

对一些开发工具的使用,例如文中所讲对内存泄漏来说有用的Memory Monitor、MAT。类如MAT的使用,很容易忘记,但是之前我写过此类文章,因此我直接去找了之前的文章,很快速的回忆起了使用步骤,很快的定位到了问题。三个字:多总结!

备注:为什么此处没有使用LeakCanary来验证猜想呢?因为事发在临上线前,我们已经关掉了LeakCanary,因此直接撸起袖子就是干,使用了这俩相对操作复杂的工具。


用户评论