android ANR发生的原因总结和解决办法

定义
主线程在特定的时间内没有做完特定的事情

常见的场景
A.input事件超过5S没有处理完成
B.service executing 超时(bind,create,start,unbind等等),前台20s,后台200s
C.广播处理超时,前台10S,后台60s
D.ContentProvider执行超时,20s
常见的原因
A.耗时操作,如复杂的layout,庞大的for循环,IO等。
B.被Binder 对端block
C.被子线程同步锁block
D.Binder被占满导致主线程无法和SystemServer通信
E.得不到系统资源(CPU/RAM/IO)
其中ABCD比较好分析,而E比较困难。
如何分析?
指导思想:通过各种线索,寻求主线程在过去一段时间内发生block的可能原因。

线索包括:
A.traces.txt/dropbox
AMS在ANR发生的时候,dump相关进程(ANR的进程、systemserver、mediaserver,surfaceFinger等)的当前栈到traces.txt。
traces.txt存在的几种形式:
1. adb pull /data/anr/
2. slog/2012xxxxx/misc/anr/snapshot_xxxx.log
3. slog/dropbox/data_app_anr_xxxxx.tgz
4. slog/dropbox/system_app_anr_xxxx.tgz
需要注意的是,traces.txt是抓取的是超时后(如input超时就是5s后)的snapshot,并不一定能够真实的反应出block的点。
也存在抓到主线程没有block,在idle的情况。
B.Eventlog中的dvm_lock_sample.
在同步锁发生content的时候,虚拟机会将这个竞争记录在eventlog中:
dvm_lock_sample: [system_server,1,Binder_7, 22, ActivityManagerService.java,15921,-,9628,4]
进程名 被block线程 block时间(ms) 被block的行号 持有者行号
实现可以参考art/runtime/monitor_android.cc LogContentionEvent函数
如果主线程是被binder对端、被同步锁block,那么eventlog中就很有可能会有dvm_lock_sample的打印。
华为项目上实现了更加强大的功能BlockMonitor,在主线程有耗时操作(如handlemsg、Binder调用耗时)的时候会打印出栈。

C.搜索主线程在发生ANR前后的main,systemlog,结合代码查看可能block在哪里。
现在发生ANR的时候,sprdruntimeinfo在mainlog中会Dump出比较多的信息,其中比较重要的是binder、cpu。
D.ANR发生的时候,打印出的CPU的占用。
注意,并不能因为有进程cpu占用高就果断的去怀疑他。
因为最主要的线索traces.txt的有效性并不是非常高,所以ANR问题分析是存在一定的局限性的。

标签: none

添加新评论