1. What's ANR
An ANR happens when some long operation takes place in the "main" thread. This is the event loop thread, and if it is busy, Android cannot process any further GUI events in the application, and thus throws up an ANR dialog. See http://developer.android.com/training/articles/perf-anr.html
2. ANR output format
ANR output displays threads information in the following order: - DVM mutexes (only for ‘main’ thread) - Thread’s info - Thread stack
1.1.DVM mutexes format
"(mutexes: tll=%x tsl=%x tscl=%x ghl=%x hwl=%x hwll=%x)", where tll - thread list lock, tsl - thread suspend lock, tscl - thread suspend count lock, dhl - GC heap lock, hwl - heap worker lock, hwll - heap worker list lock |
1.2.Thread's info format Thread’s info format - first line
“%name %priority %tid %status”, where name - thread name, priority - thread priority, tid - thread id, status - thread status |
Thread’s info format - second line
" group=%s sCount=%d dsCount=%d obj=%p self=%p“, where group - group name, sCount - suspend count, dsCount - debug suspend count, obj - Linux thread that we are associated with self - self reference |
Thread’s info format - third line
" sysTid=%d nice=%d sched=%d/%d cgrp=%s handle=%d", where sysTid - Linux thread id, nice - Linux "nice“ priority (lower numbers indicate higher priority), sched - scheduling priority, cgrp - scheduling group buffer handle - thread handle |
Stack trace The stack trace contains functions call stack at the moment ‘dumpstate’ command was called. If the thread is in the TIMED_WAIT state it also contains the address of the object the current thread is waiting for e.g
2. Thread status
Thread status can be one of the following values:
ZOMBIE - terminated thread RUNNABLE - runnable or running now TIMED_WAIT - timed waiting in Object.wait() MONITOR - blocked on a monitor WAIT - waiting in Object.wait() INITIALIZING - allocated, not yet running STARTING - started, not yet on thread list NATIVE - off in a JNI native method VMWAIT - waiting on a VM resource SUSPENDED - suspended, usually by GC or debugger UNKNOWN - thread is in the undefined state |
3. Example. Here's a Normandy ANR error and how I identified it by checking trace.
1. Check android.server.ServerThread->search 'waiting to lock'->get 'held by..'. Searching 'waiting' is more genetically
1281 "android.server.ServerThread" prio=5 tid=12 MONITOR 1282 | group="main" sCount=1 dsCount=0 obj=0x424f1fd8 self=0x4f810008 1283 | sysTid=583 nice=-2 sched=0/0 cgrp=apps handle=1337892560 1284 | schedstat=( 0 0 0 ) utm=1196 stm=106 core=0 1285 at com.android.server.AlarmManagerService$ResultReceiver.onSendFinished(AlarmManagerService.java:~1034) 1286 - waiting to lock <0x42876cb8> (a java.lang.Object) held by tid=23 (AlarmManager) |
2. In this case, search AlarmManager? based on what we got in 'held by..' of step 1
1070 "AlarmManager" prio=5 tid=23 MONITOR 1071 | group="main" sCount=1 dsCount=0 obj=0x42985c58 self=0x4fd91a78 1072 | sysTid=639 nice=0 sched=0/0 cgrp=apps handle=1337835624 1073 | schedstat=( 0 0 0 ) utm=15 stm=5 core=0 1074 at com.android.server.PowerManagerService.acquireWakeLock(PowerManagerService.java:~911) 1075 - waiting to lock <0x424feaf8> (a com.android.server.PowerManagerService$LockList) held by tid=9 (Binder_1) |
3. check 'Binger_1' from step 2 to figure out where's lock place in source.
1324 "Binder_1" prio=5 tid=9 NATIVE 1325 | group="main" sCount=1 dsCount=0 obj=0x424ed8e8 self=0x50bae4b0 1326 | sysTid=580 nice=0 sched=0/0 cgrp=apps handle=1345522072 1327 | schedstat=( 0 0 0 ) utm=1745 stm=912 core=0 1328 at com.android.server.PowerManagerService.nativeSetScreenState(Native Method) 1329 at com.android.server.PowerManagerService.setScreenStateLocked(PowerManagerService.java:1928) 1330 at com.android.server.PowerManagerService.setPowerState(PowerManagerService.java:2060) 1331 at com.android.server.PowerManagerService.setPowerState(PowerManagerService.java:1963) 1332 at com.android.server.PowerManagerService.acquireWakeLockLocked(PowerManagerService.java:1063) 1333 at com.android.server.PowerManagerService.acquireWakeLock(PowerManagerService.java:912) 1334 at android.os.IPowerManager$Stub.onTransact(IPowerManager.java:62) 1335 at android.os.Binder.execTransact(Binder.java:367) 1336 at dalvik.system.NativeStart.run(Native Method) |
Here's PowerManagerService?.java:~911
900 public void acquireWakeLock(int flags, IBinder lock, String tag, WorkSource ws) { 901 int uid = Binder.getCallingUid(); 902 int pid = Binder.getCallingPid(); 903 if (uid != Process.myUid()) { 904 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 905 } 906 if (ws != null) { 907 enforceWakeSourcePermission(uid, pid); 908 } 909 long ident = Binder.clearCallingIdentity(); 910 try { >> 911 synchronized (mLocks) { 912 acquireWakeLockLocked(flags, lock, uid, pid, tag, ws); 913 } 914 } finally { 915 Binder.restoreCallingIdentity(ident); 916 } 917 } |
No comments:
Post a Comment