浅谈ANR及如何分析解决ANR.docx
《浅谈ANR及如何分析解决ANR.docx》由会员分享,可在线阅读,更多相关《浅谈ANR及如何分析解决ANR.docx(14页珍藏版)》请在冰点文库上搜索。
浅谈ANR及如何分析解决ANR
浅谈ANR及如何分析解决ANR
浅谈ANR及如何分析解决ANR
一:
什么是ANR
ANR:
ApplicationNotResponding,即应用无响应
二:
ANR的类型
ANR一般有三种类型:
1:
KeyDispatchTimeout(5seconds)--主要类型
按键或触摸事件在特定时间内无响应
2:
BroadcastTimeout(10seconds)
BroadcastReceiver在特定时间内无法处理完成
3:
ServiceTimeout(20seconds)--小概率类型
Service在特定的时间内无法处理完成
三:
KeyDispatchTimeout
Akeyortoucheventwasnotdispatchedwithinthespecifiedtime(按键或触摸事件在特定时间内无响应)
具体的超时时间的定义在framework下的
ActivityManagerService.java
//Howlongwewaituntilwetimeoutonkeydispatching.
staticfinalintKEY_DISPATCHING_TIMEOUT=5*1000
四:
为什么会超时呢?
超时时间的计数一般是从按键分发给app开始。
超时的原因一般有两种:
(1)当前的事件没有机会得到处理(即UI线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了)
(2)当前的事件正在处理,但没有及时完成
五:
如何避免KeyDispatchTimeout
1:
UI线程尽量只做跟UI相关的工作
2:
耗时的工作(比如数据库操作,I/O,连接网络或者别的有可能阻碍UI线程的操作)把它放入单独的线程处理
3:
尽量用Handler来处理UIthread和别的thread之间的交互六:
UI线程
说了那么多的UI线程,那么哪些属于UI线程呢?
UI线程主要包括如下:
1.ActivitynCreate(),onResume(),onDestroy(),onKeyDown(),onClick(),etc
2.AsyncTask:
onPreExecute(),onProgressUpdate(),onPostExecute(),onCancel,etc
3.Mainthreadhandler:
handleMessage(),post*(runnabler),etc
4.other七:
如何去分析ANR
先看个LOG:
04-0113:
12:
11.572I/InputDispatcher(220):
Applicationisnotresponding:
Window{2b263310com.android.email/com.android.email.activity.SplitScreenActivitypaused=false}.5009.8mssinceevent,5009.5mssincewaitstarted
04-0113:
12:
11.572I/WindowManager(220):
Inputeventdispatchingtimedoutsendingtocom.android.email/com.android.email.activity.SplitScreenActivity
04-0113:
12:
14.123I/Process(220):
Sendingsignal.PID:
21404SIG:
3---发生ANR的时间和生成trace.txt的时间
04-0113:
12:
14.123I/dalvikvm(21404):
threadid=4:
reactingtosignal3
……
04-0113:
12:
15.872E/ActivityManager(220):
ANRincom.android.email(com.android.email/.activity.SplitScreenActivity)
04-0113:
12:
15.872E/ActivityManager(220):
Reason:
keyDispatchingTimedOut
04-0113:
12:
15.872E/ActivityManager(220):
Load:
8.68/8.37/8.53
04-0113:
12:
15.872E/ActivityManager(220):
CPUusagefrom4361msto699msago----CPU在ANR发生前的使用情况04-0113:
12:
15.872E/ActivityManager(220):
5.5%21404/com.android.email:
1.3%user+4.1%kernel/faults:
10minor
04-0113:
12:
15.872E/ActivityManager(220):
4.3%220/system_server:
2.7%user+1.5%kernel/faults:
11minor2major
04-0113:
12:
15.872E/ActivityManager(220):
0.9%52/spi_qsd.0:
0%user+0.9%kernel
04-0113:
12:
15.872E/ActivityManager(220):
0.5%65/irq/170-cyttsp-:
0%user+0.5%kernel
04-0113:
12:
15.872E/ActivityManager(220):
0.5%296/com.android.systemui:
0.5%user+0%kernel
04-0113:
12:
15.872E/ActivityManager(220):
100%TOTAL:
4.8%user+7.6%kernel+87%iowait
04-0113:
12:
15.872E/ActivityManager(220):
CPUusagefrom3697msto4223mslater:
--ANR后CPU的使用量
04-0113:
12:
15.872E/ActivityManager(220):
25%21404/com.android.email:
25%user+0%kernel/faults:
191minor
04-0113:
12:
15.872E/ActivityManager(220):
16%21603/__eas(par.hakan:
16%user+0%kernel
04-0113:
12:
15.872E/ActivityManager(220):
7.2%21406/GC:
7.2%user+0%kernel
04-0113:
12:
15.872E/ActivityManager(220):
1.8%21409/Compiler:
1.8%user+0%kernel
04-0113:
12:
15.872E/ActivityManager(220):
5.5%220/system_server:
0%user+5.5%kernel/faults:
1minor
04-0113:
12:
15.872E/ActivityManager(220):
5.5%263/InputDispatcher:
0%user+5.5%kernel
04-0113:
12:
15.872E/ActivityManager(220):
32%TOTAL:
28%user+3.7%kernel从LOG可以看出ANR的类型,CPU的使用情况,如果CPU使用量接近100%,说明当前设备很忙,有可能是CPU饥饿导致了ANR
如果CPU使用量很少,说明主线程被BLOCK了
如果IOwait很高,说明ANR有可能是主线程在进行I/O操作造成的
除了看LOG,解决ANR还得需要trace.txt文件,
如何获取呢?
可以用如下命令获取
1.$chmod777/data/anr
2.$rm/data/anr/traces.txt
3.$ps
4.$kill-3PID
5.adbpulldata/anr/traces.txt./mytraces.txt
从trace.txt文件,看到最多的是如下的信息:
-----pid21404at2011-04-0113:
12:
14-----
Cmdline:
com.android.emailDALVIKTHREADS:
(mutexes:
tll=0tsl=0tscl=0ghl=0hwl=0hwll=0)
"main"prio=5tid=1NATIVE
|group="main"sCount=1dsCount=0obj=0x2aad2248self=0xcf70
|sysTid=21404nice=0sched=0/0cgrp=[fopen-error:
2]handle=1876218976
atandroid.os.MessageQueue.nativePollOnce(NativeMethod)
atandroid.os.MessageQueue.next(MessageQueue.java:
119)
atandroid.os.Looper.loop(Looper.java:
110)
atandroid.app.ActivityThread.main(ActivityThread.java:
3688)
atjava.lang.reflect.Method.invokeNative(NativeMethod)
atjava.lang.reflect.Method.invoke(Method.java:
507)
atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:
866)
atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:
624)
atdalvik.system.NativeStart.main(NativeMethod)
说明主线程在等待下条消息进入消息队列
八:
Thread状态
ThreadState(definedat“dalvik/vm/thread.h“)
THREAD_UNDEFINED=-1,/*makesenumcompatiblewithint32_t*/
THREAD_ZOMBIE=0,/*TERMINATED*/
THREAD_RUNNING=1,/*RUNNABLEorrunningnow*/
THREAD_TIMED_WAIT=2,/*TIMED_WAITINGinObject.wait()*/
THREAD_MONITOR=3,/*BLOCKEDonamonitor*/
THREAD_WAIT=4,/*WAITINGinObject.wait()*/
THREAD_INITIALIZING=5,/*allocated,notyetrunning*/
THREAD_STARTING=6,/*started,notyetonthreadlist*/
THREAD_NATIVE=7,/*offinaJNInativemethod*/
THREAD_VMWAIT=8,/*waitingonaVMresource*/
THREAD_SUSPENDED=9,/*suspended,usuallybyGCordebugger*/九:
如何调查并解决ANR
1:
首先分析log
2:
从trace.txt文件查看调用stack.
3:
看代码
4:
仔细查看ANR的成因(iowait?
block?
memoryleak?
)十:
案例
案例1:
关键词:
ContentResolverinAsyncTaskonPostExecute,highiowait
Process:
com.android.email
Activity:
com.android.email/.activity.MessageView
Subject:
keyDispatchingTimedOut
CPUusagefrom2550msto-2814msago:
5%187/system_server:
3.5%user+1.4%kernel/faults:
86minor20major
4.4%1134/com.android.email:
0.7%user+3.7%kernel/faults:
38minor19major
4%372/com.android.eventstream:
0.7%user+3.3%kernel/faults:
6minor
1.1%272/com.android.phone:
0.9%user+0.1%kernel/faults:
33minor
0.9%252/com.android.systemui:
0.9%user+0%kernel
0%409/com.android.eventstream.telephonyplugin:
0%user+0%kernel/faults:
2minor
0.1%632/com.android.devicemonitor:
0.1%user+0%kernel
100%TOTAL:
6.9%user+8.2%kernel+84%iowait-----pid1134at2010-12-1717:
46:
51-----
Cmdline:
com.android.emailDALVIKTHREADS:
(mutexes:
tll=0tsl=0tscl=0ghl=0hwl=0hwll=0)
"main"prio=5tid=1WAIT
|group="main"sCount=1dsCount=0obj=0x2aaca180self=0xcf20
|sysTid=1134nice=0sched=0/0cgrp=[fopen-error:
2]handle=1876218976
atjava.lang.Object.wait(NativeMethod)
-waitingon<0x2aaca218>(ajava.lang.VMThread)
atjava.lang.Thread.parkFor(Thread.java:
1424)
atjava.lang.LangAccessImpl.parkFor(LangAccessImpl.java:
48)
atsun.misc.Unsafe.park(Unsafe.java:
337)
atjava.util.concurrent.locks.LockSupport.park(LockSupport.java:
157)
atjava.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:
808)
atjava.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:
841)
atjava.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:
1171)
atjava.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:
200)
atjava.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:
261)
atandroid.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:
378)
atandroid.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.java:
222)
atandroid.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:
53)
atandroid.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:
1356)
atandroid.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:
1235)
atandroid.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:
1189)
atandroid.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:
1271)
atcom.android.email.provider.EmailProvider.query(EmailProvider.java:
1098)
atandroid.content.ContentProvider$Transport.query(ContentProvider.java:
187)
atandroid.content.ContentResolver.query(ContentResolver.java:
268)
atcom.android.email.provider.EmailContent$Message.restoreMessageWithId(EmailContent.java:
648)
atcom.android.email.Controller.setMessageRead(Controller.java:
658)
atcom.android.email.activity.MessageView.onMarkAsRead(MessageView.java:
700)
atcom.android.email.activity.MessageView.access$2500(MessageView.java:
98)
atcom.android.email.activity.MessageView$LoadBodyTask.onPostExecute(MessageView.java:
1290)
atcom.android.email.activity.MessageView$LoadBodyTask.onPostExecute(MessageView.java:
1255)
atandroid.os.AsyncTask.finish(AsyncTask.java:
417)
atandroid.os.AsyncTask.access$300(AsyncTask.java:
127)
atandroid.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:
429)
atandroid.os.Handler.dispatchMessage(Handler.java:
99)
atandroid.os.Looper.loop(Looper.java:
123)
atandroid.app.ActivityThread.main(ActivityThread.java:
3652)
atjava.lang.reflect.Method.invokeNative(NativeMethod)
atjava.lang.reflect.Method.invoke(Method.java:
507)
atcom.android.internal.os.ZygoteIn
原因:
IOWait很高,说明当前系统在忙于I/O,因此数据库操作被阻塞
原来:
finalMessagemessage=Message.restoreMessageWithId(mProviderContext,messageId);
if(message==null){
return;
}
Accountaccount=Account.restoreAccountWithId(mProviderContext,message.mAccountKey);
if(account==null){
return;//isMessagingControllerreturnsfalsefornull,butlet'smakeitclear.
}
if(isMessagingController(account)){
newThread(){
@Override
publicvoidrun(){
mLegacyController.processPendingActions(message.mAccountKey);
}
}.start();
}解决后:
newThread(){
finalMessagemessage=Message.restoreMessageWithId(mProviderContext,messageId);
if(message==null){
return;
}
Accountaccount=Account.restoreAccountWithId(mProviderContext,message.mAccountKey);
if(account==null){
return;//isMessagingControllerreturnsfalsefornull,butlet'smakeitclear.
}
if(isMessagingController(account)){
mLegacyController.processPendingActions(message.mAccountKey);
}}.start();
关于AsyncTask:
ANRinprocess:
com.android.me