一瘸味、前言
此文主要記錄發(fā)生ANR時生成的traces.txt文檔,便于記憶分析彻坛。
ANR中的traces.txt文檔是利用了Linux信號機制,APP監(jiān)聽到主線程卡頓的時候踏枣,進程便會發(fā)送SIGQUIT的信號昌屉,然后作為相對應(yīng)的操作,生成日志茵瀑。所以通過以下命令间驮,向進程發(fā)送信號,也會有同樣的效果马昨。
adb shell kill -3 [pid]
二竞帽、traces.txt
以下是簡略的traces.txt文件:
----- pid 1528 at 2019-07-22 15:12:00 -----
Cmd line: com.idata.mdm
Build fingerprint: 'alps/full_bd6737t_35g_a_m0/bd6737t_35g_a_m0:6.0/MRA58K/1528710497:user/dev-keys'
ABI: 'arm'
Build type: optimized
Zygote loaded classes=4112 post zygote classes=133
Intern table: 59969 strong; 17 weak
JNI: CheckJNI is off; globals=311 (plus 360 weak)
.......
Total time spent in GC: 3.346s
// GC的吞吐量
Mean GC size throughput: 50MB/s
Mean GC object throughput: 674461 objects/s
Total number of allocations 2303118
Total bytes allocated 177MB
Total bytes freed 168MB
Free memory 303KB
Free memory until GC 303KB
Free memory until OOME 118MB
Total memory 9MB
Max memory 128MB
Zygote space size 2MB
Total mutator paused time: 143.861ms
Total time waiting for GC to complete: 693.458us
// GC發(fā)生的次數(shù)
Total GC count: 190
// GC消耗的時間
Total GC time: 3.346s
// 阻塞GC發(fā)生的次數(shù) 阻塞GC執(zhí)行之時會暫停其他的線程
Total blocking GC count: 0
// 阻塞GC消耗的時間
Total blocking GC time: 0
Histogram of GC count per 10000 ms: 0:36478,1:126,3:4,4:10,5:1,6:1
Histogram of blocking GC count per 10000 ms: 0:36620
// main 代表線程名稱
// prio = 優(yōu)先級
// Native = 代表當前線程的狀態(tài),Native代表執(zhí)行JNI代碼
"main" prio=5 tid=1 Native
//group是線程組名稱 sCount是線程被掛起的次數(shù) dsCount是線程調(diào)試狀態(tài)下掛起的次數(shù)
//obj是這個線程的Java對象的地址 self表是這個線程Native的地址鸿捧。
| group="main" sCount=1 dsCount=0 obj=0x758f72e8 self=0xb7ce4b78
// sysTid 是此線程在內(nèi)核中對應(yīng)的線程ID
// nice 代表著struct_task任務(wù)被調(diào)度的優(yōu)先級
// cgrp是調(diào)度組 sched分別是線程的調(diào)度策略和優(yōu)先級 handle是線程的處理函數(shù)地址屹篓。
| sysTid=1528 nice=0 cgrp=default sched=0/0 handle=0xb6f80de4
//state = native 線程狀態(tài) schedstat值來自于/proc/[pid]/task/[tid]/schedstat,分別是cpu上執(zhí)行的時間匙奴、線程的等待時間和線程執(zhí)行的時間片
// utm是線程用戶態(tài)下執(zhí)行時間 stm是內(nèi)核態(tài)下執(zhí)行時間(單位是jiffies) HZ可推出執(zhí)行時間 stm = 747*1000/100
| state=S schedstat=( 31041259455 5111094667 27821 ) utm=2357 stm=747 core=0 HZ=100
| stack=0xbe3a6000-0xbe3a8000 stackSize=8MB
| held mutexes=
at android.os.MessageQueue.nativePollOnce(Native method)
at android.os.MessageQueue.next(MessageQueue.java:328)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:5765)
at java.lang.reflect.Method.invoke!(Native method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
三堆巧、線程模型及線程狀態(tài)
對于上述線程狀態(tài),相對于java線程狀態(tài)泼菌,Linux細化了很多狀態(tài)谍肤,這樣更便于分析當前的狀態(tài)。
java中的線程和操作系統(tǒng)內(nèi)核中的線程并不是等價關(guān)系灶轰。他們之間存在著映射關(guān)系谣沸,對Android來說,java中的線程和內(nèi)核的線程是一對一關(guān)系笋颤。
線程狀態(tài)