@ZeroGeek
2018-07-31T02:22:55.000000Z
字数 2942
阅读 2103
Android高工成长之路
指应用程序(具体指应用组件)不能响应用户的操作。
Android应用运行在一个线程中(称为UI线程或主线程)。一但这个线程被阻塞时间过长,则无法响应用户的操作或intent broadcasts。系统不允许这种情况,所以系统会弹窗提示抛出ANR。
应用程序的响应是由ActivityManager和WindowManager等系统服务监视的,当检测到下面情况的任何一种时,Android就会针对特定的应用程序显示ANR对话框。
应在主线程做尽可能少的事情。耗时的工作(网络、数据库、大量计算、图片处理等)交给子线程处理。
老版本目录:/data/anr/traces.txt
新版本目录:/data/anr/anr_*
adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>
07-25 14:07:21.053 1471-29421/? E/ActivityManager: ANR in com.mymoney (com.mymoney/.biz.account.activity.SelectAccountOrgActivity)
PID: 28867
Reason: Input dispatching timed out (Waiting to send key event because the focused window has not finished processing all of the input events that were previously delivered to it. Outbound queue length: 0. Wait queue length: 2.), happend at time = 6940397@#@28867
Load: 0.0 / 0.0 / 0.0
CPU usage from 141511ms to 0ms ago with 99% awake:
这类问题是主线程正在执行其他的事件但是比较耗时导致输入事件无法及时处理。
同时看到CPU是满负荷情况,99% awake。
通常由Moneky跑出来的。
从设备中拷贝出ANR日志后,先找到应用ANR的位置:
----- pid 32758 at 2018-07-25 07:58:27 -----
Cmd line: com.mymoney // 锁定包名
可以看到此时内存已经被占满
Heap: 0% free, 127MB/128MB; 513576 objects
接下来主要分析主线程的情况
DALVIK THREADS (71):
"main" prio=5 tid=1 Waiting // 主线程,处于等待状态
| group="main" sCount=2 dsCount=0 obj=0x758fe248 self=0xb4d07800
| sysTid=32758 nice=-6 cgrp=apps sched=0/0 handle=0xb6f08ec8
| state=S schedstat=( 0 0 0 ) utm=91621 stm=11873 core=1 HZ=100
| stack=0xbe761000-0xbe763000 stackSize=8MB
| held mutexes=
at java.lang.Object.wait!(Native method)
- waiting on <0x09315ca1> (a android.app.SharedPreferencesImpl)
at android.app.SharedPreferencesImpl.awaitLoadedLocked(SharedPreferencesImpl.java:206)
at android.app.SharedPreferencesImpl.getLong(SharedPreferencesImpl.java:245)
- locked <0x09315ca1> (a android.app.SharedPreferencesImpl)
at hgu.b(ExceptionHandler.java:63)
at hgu.a(ExceptionHandler.java:56)
at hgu.uncaughtException(ExceptionHandler.java:41)
at com.flurry.sdk.od$a.uncaughtException(SourceFile:2088)
at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
第11行看到主线程执行了SharedPreference的getLong,并处于等待锁状态。因为SharedPreferencesImpl初始化时,会开启一个子线程从磁盘加载数据到内存中,此时会持有锁并阻塞其它线程的操作直到加载完成才释放锁。但是由于内存不足,会频繁触发GC操作,而GC操作又会阻塞其它所有线程的执行,从而导致主线程等待超时产生ANR。
如何解决这个问题呢?
1.整体上做内存优化
2.提前初始化SharedPreferencesImpl
3.减少SharedPreference的存储数据量
拿到一份ANR的完整日志,一般步骤如下: