版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接和本聲明。
-
什麼是ANR?html
ANR:Application Not Responding,即應用無響應java
-
ANR日誌Trace文件獲取android
系統生成的Trace文件保存在data/anr,能夠用過命令adb pull data/anr/取出web
traces.txt只保留最後一次ANR的信息,Android系統有個DropBox功能功能,它能記錄系統出現的crash錯誤.所以保留有發生過的ANR的信息.(log路徑:/data/system/dropbox)shell
獲取系統crash log: adb shell dumpsys dropbox --print >>log.txt數據庫
-
-
當
APP(包括系統APP和用戶APP)進程出現ANR、應用響應慢或WatchDog的監視沒有獲得回饋時,
-
系統會
dump此時的top進程,進程中Thread的運行狀態就都dump到這個Trace文件中了.
-
致使ANR的常見幾種狀況:網絡
1:Input dispatching timed out(5 seconds) 按鍵或觸摸事件處理超時(通常是UI主線程作了耗時的操做,這類ANR最多見)app
2:BroadcastTimeout(10 seconds) 廣播的分發和處理超時(通常是onReceiver執行時間過長)ide
3:ServiceTimeout(20 seconds) Service的啓動和執行超時函數
另外還有ProviderTimeout和WatchDog等致使的ANR.還有當系統內存或CPU資源不足時容易出現ANR,通常這種狀況會有lowmemorykill的log打印.
應用ANR產生的時候,ActivityManagerService的appNotResponding方法就會被調用,而後在/data/anr/traces.txt文件中寫入ANR相關信息.
-
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
-
ActivityRecord parent, boolean aboveSystem, final String annotation) {
-
-
-
-
-
-
final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
-
-
File tracesFile = dumpStackTraces(
true, firstPids, processCpuTracker, lastPids,
-
NATIVE_STACKS_OF_INTEREST);
-
-
-
-
-
synchronized (mProcessCpuTracker) {
-
-
cpuInfo = mProcessCpuTracker.printCurrentState(anrTime);
-
-
info.append(processCpuTracker.printCurrentLoad());
-
-
-
-
info.append(processCpuTracker.printCurrentState(anrTime));
-
-
Slog.e(TAG, info.toString());
-
if (tracesFile == null) {
-
-
Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
-
-
-
addErrorToDropBox(
"anr", app, app.processName, activity, parent, annotation,
-
cpuInfo, tracesFile,
null);
-
-
-
-
-
Message msg = Message.obtain();
-
HashMap<String, Object> map =
new HashMap<String, Object>();
-
msg.what = SHOW_NOT_RESPONDING_MSG;
-
-
msg.arg1 = aboveSystem ?
1 : 0;
-
-
-
map.put(
"activity", activity);
-
-
mUiHandler.sendMessage(msg);
-
-
避免ANR?
-
UI線程儘可能只作跟UI相關的工做
-
耗時的工做(好比數據庫操做,I/O,鏈接網絡或者別的有可能阻礙UI線程的操做)把它放入單獨的線程處理
-
儘可能用Handler來處理UIthread和別的thread之間的交互
分析ANR的Log:
出現ANR的log以下:
-
06-22 10:37:46.204 3547 3604 E ActivityManager: ANR in org.code:MessengerService // ANR出現的進程包名
-
-
E ActivityManager: PID: 17027 // ANR進程ID
-
-
E ActivityManager: Reason: executing service org.code/.ipc.MessengerService //致使ANR的緣由
-
-
E ActivityManager:
Load: 8.31 / 8.12 / 8.47
-
-
E ActivityManager: CPU
usage from 0ms to 6462ms later: //CPU在ANR發生後的使用狀況
-
-
E ActivityManager:
61% 3547/system_server: 21% user + 39% kernel / faults: 13302 minor 2 major
-
-
E ActivityManager:
0.2% 475/debuggerd: 0% user + 0.1% kernel / faults: 6086 minor 1 major
-
-
E ActivityManager:
10% 5742/com.android.phone: 5.1% user + 5.1% kernel / faults: 7597 minor
-
-
E ActivityManager:
6.9% 5342/com.android.systemui: 2.1% user + 4.8% kernel / faults: 4158 minor
-
-
E ActivityManager:
0.1% 477/debuggerd64: 0% user + 0.1% kernel / faults: 4013 minor
-
-
E ActivityManager:
5.7% 16313/org.code: 3.2% user + 2.4% kernel / faults: 2412 minor
-
-
E ActivityManager:
3.7% 17027/org.code:MessengerService: 1.7% user + 2% kernel / faults: 2571 minor 6 major
-
-
E ActivityManager:
2.6% 306/cfinteractive: 0% user + 2.6% kernel
-
-
E ActivityManager: +
0% 17168/kworker/0:1: 0% user + 0% kernel
-
-
E ActivityManager:
0% TOTAL: 0% user + 0% kernel + 0% softirq // CUP佔用狀況
-
-
E ActivityManager: CPU
usage from 5628ms to 6183ms later:
-
-
E ActivityManager:
42% 3547/system_server: 17% user + 24% kernel / faults: 11 minor
-
-
E ActivityManager:
12% 3604/ActivityManager: 1.7% user + 10% kernel
-
-
E ActivityManager:
12% 3609/android.display: 8.7% user + 3.5% kernel
-
-
E ActivityManager:
3.5% 5304/Binder_6: 1.7% user + 1.7% kernel
-
-
E ActivityManager:
3.5% 5721/Binder_A: 1.7% user + 1.7% kernel
-
-
E ActivityManager:
3.5% 5746/Binder_C: 3.5% user + 0% kernel
-
-
E ActivityManager:
1.7% 3599/Binder_1: 0% user + 1.7% kernel
-
-
E ActivityManager:
1.7% 3600/Binder_2: 0% user + 1.7% kernel
-
-
I ActivityManager: Killing
17027:org.code:MessengerService/u0a85 (adj 1): bg anr
-
-
I art : Wrote stack traces
to '/data/anr/traces.txt' //art這個TAG打印對traces操做的信息
-
-
D GraphicsStats: Buffer
count: 9
-
-
W ActivityManager: Scheduling restart
of crashed service org.code/.ipc.MessengerService in 1000ms
-
log打印了ANR的基本信息,咱們能夠分析CPU使用率推測ANR發生的時候設備在作什麼工做;若是CPU使用率很高,接近100%,多是在進行大規模的計算更多是陷入死循環;若是CUP使用率很低,說明主線程被阻塞了,而且當IOwait很高,多是主線程在等待I/O操做的完成.
對於ANR只是分析Log很難知道問題所在,咱們還須要經過Trace文件分析stack調用狀況.
-
-
----- pid
17027 at 2017-06-22 10:37:39 -----
-
Cmd line: org.code:MessengerService
-
Build fingerprint:
'Homecare/qucii8976v3_64:6.0.1/pansen06141150:eng/test-keys'
-
-
-
Zygote loaded classes=
6576 post zygote classes=13
-
Intern table:
13780 strong; 17 weak
-
JNI: CheckJNI is on; globals=
283 (plus 158 weak)
-
Libraries: /system/lib64/libandroid.so /system/lib64/libcompiler_rt.so /system/lib64/libjavacrypto.so /system/lib64/libjnigraphics.so /system/lib64/libmedia_jni.so /system/lib64/libwebviewchromium_loader.so libjavacore.so (
7)
-
Heap:
29% free, 8MB/12MB; 75731 objects
-
Dumping cumulative Gc timings
-
Total number of allocations
75731
-
Total bytes allocated
8MB
-
-
-
-
Free memory until OOME
183MB
-
-
-
-
Total mutator paused time:
0
-
Total time waiting
for GC to complete: 0
-
-
-
Total blocking GC count:
0
-
Total blocking GC time:
0
-
-
suspend all histogram: Sum:
76us 99% C.I. 0.100us-28us Avg: 7.600us Max: 28us
-
-
-
-
"Signal Catcher" daemon prio=5 tid=3 Runnable
-
-
| group=
"system" sCount=0 dsCount=0 obj=0x12d8f0a0 self=0x5598ae55d0
-
-
| sysTid=
17033 nice=0 cgrp=default sched=0/0 handle=0x7fb2350450
-
| state=R schedstat=(
4348125 172343 3 ) utm=0 stm=0 core=1 HZ=100
-
| stack=
0x7fb2254000-0x7fb2256000 stackSize=1013KB
-
| held mutexes=
"mutator lock"(shared held)
-
-
-
-
-
-
-
-
-
-
-
-
(no managed stack frames)
-
-
-
"main" prio=5 tid=1 Sleeping
-
| group=
"main" sCount=1 dsCount=0 obj=0x73132d10 self=0x5598a5f5e0
-
-
| sysTid=
17027 nice=0 cgrp=default sched=0/0 handle=0x7fb6db6fe8
-
| state=S schedstat=(
420582038 5862546 143 ) utm=24 stm=18 core=6 HZ=100
-
| stack=
0x7fefba3000-0x7fefba5000 stackSize=8MB
-
-
-
at java.lang.Thread.sleep!(Native method)
-
- sleeping on <
0x0c60f3c7> (a java.lang.Object)
-
at java.lang.Thread.sleep(Thread.java:
1031)
-
- locked <
0x0c60f3c7> (a java.lang.Object)
-
at java.lang.Thread.sleep(Thread.java:
985)
-
at android.os.SystemClock.sleep(SystemClock.java:
120)
-
at org.code.ipc.MessengerService.onCreate(MessengerService.java:
63)
-
at android.app.ActivityThread.handleCreateService(ActivityThread.java:
2877)
-
at android.app.ActivityThread.access$
1900(ActivityThread.java:150)
-
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:
1427)
-
at android.os.Handler.dispatchMessage(Handler.java:
102)
-
at android.os.Looper.loop(Looper.java:
148)
-
at android.app.ActivityThread.main(ActivityThread.java:
5417)
-
at java.lang.reflect.Method.invoke!(Native method)
-
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:
726)
-
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:
616)
在log中顯示的pid在traces文件中與之對應,trace log中會打印當前全部線程的堆棧信息,通常咱們主要關注main線程的堆棧(也有分析其餘線程的狀況,經過分析ANR發生時系統狀態推測出設備正在進行操做)
而這裏而後經過查看堆棧調用信息分析ANR的代碼.上述ANR實際上在org.code.ipc.MessengerService.onCreate中63行調用SystemClock.sleep(10000)代碼致使的;這是比較簡單ANR示例.
以上僅爲解決ANR問題提供一個思路,具體問題還須要根據實際狀況具體分析
線程狀態的分類: java中定義的線程狀態:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
C代碼中定義的線程狀態:
-
/
/ /art/runtime/thread_state.h
-
-
// Thread.State JDWP state
-
kTerminated =
66, // TERMINATED TS_ZOMBIE Thread.run has returned, but Thread* still around
-
kRunnable,
// RUNNABLE TS_RUNNING runnable
-
kTimedWaiting,
// TIMED_WAITING TS_WAIT in Object.wait() with a timeout
-
kSleeping,
// TIMED_WAITING TS_SLEEPING in Thread.sleep()
-
kBlocked,
// BLOCKED TS_MONITOR blocked on a monitor
-
kWaiting,
// WAITING TS_WAIT in Object.wait()
-
kWaitingForGcToComplete,
// WAITING TS_WAIT blocked waiting for GC
-
kWaitingForCheckPointsToRun,
// WAITING TS_WAIT GC waiting for checkpoints to run
-
kWaitingPerformingGc,
// WAITING TS_WAIT performing GC
-
kWaitingForDebuggerSend,
// WAITING TS_WAIT blocked waiting for events to be sent
-
kWaitingForDebuggerToAttach,
// WAITING TS_WAIT blocked waiting for debugger to attach
-
kWaitingInMainDebuggerLoop,
// WAITING TS_WAIT blocking/reading/processing debugger events
-
kWaitingForDebuggerSuspension,
// WAITING TS_WAIT waiting for debugger suspend all
-
kWaitingForJniOnLoad,
// WAITING TS_WAIT waiting for execution of dlopen and JNI on load code
-
kWaitingForSignalCatcherOutput,
// WAITING TS_WAIT waiting for signal catcher IO to complete
-
kWaitingInMainSignalCatcherLoop,
// WAITING TS_WAIT blocking/reading/processing signals
-
kWaitingForDeoptimization,
// WAITING TS_WAIT waiting for deoptimization suspend all
-
kWaitingForMethodTracingStart,
// WAITING TS_WAIT waiting for method tracing to start
-
kWaitingForVisitObjects,
// WAITING TS_WAIT waiting for visiting objects
-
kWaitingForGetObjectsAllocated,
// WAITING TS_WAIT waiting for getting the number of allocated objects
-
kStarting,
// NEW TS_WAIT native thread started, not yet ready to run managed code
-
kNative,
// RUNNABLE TS_RUNNING running in a JNI native method
-
kSuspended,
// RUNNABLE TS_RUNNING suspended by GC or debugger
-
二者能夠看出在C代碼中定義更爲詳細,Traces中顯示的線程狀態都是C代碼定義的.咱們能夠經過查看線程狀態對應的信息分析ANR問題.
如: TimedWaiting對應的線程狀態是TIMED_WAITING
kTimedWaiting, // TIMED_WAITING TS_WAIT in Object.wait() with a timeout 執行了無超時參數的wait函數
kSleeping, // TIMED_WAITING TS_SLEEPING in Thread.sleep() 執行了帶有超時參數的sleep函數
-
-
RUNNING/RUNNABLE 線程可運行或正在運行
-
TIMED_WAIT 執行了帶有超時參數的
wait、sleep或join函數
-
-
-
INITIALIZING 新建,正在初始化,爲其分配資源
-
-
-
-
SUSPENDED 線程暫停,一般是因爲GC或debug被暫停