一、前言
此文主要记录发生ANR时生成的traces.txt文档,便于记忆分析。
ANR中的traces.txt文档是利用了Linux信号机制,APP监听到主线程卡顿的时候,进程便会发送SIGQUIT的信号,然后作为相对应的操作,生成日志。所以通过以下命令,向进程发送信号,也会有同样的效果。
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发生的次数
Total GC count: 190
// GC消耗的时间
Total GC time: 3.346s
// 阻塞GC发生的次数 阻塞GC执行之时会暂停其他的线程
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 = 优先级
// Native = 代表当前线程的状态,Native代表执行JNI代码
"main" prio=5 tid=1 Native
//group是线程组名称 sCount是线程被挂起的次数 dsCount是线程调试状态下挂起的次数
//obj是这个线程的Java对象的地址 self表是这个线程Native的地址。
| group="main" sCount=1 dsCount=0 obj=0x758f72e8 self=0xb7ce4b78
// sysTid 是此线程在内核中对应的线程ID
// nice 代表着struct_task任务被调度的优先级
// cgrp是调度组 sched分别是线程的调度策略和优先级 handle是线程的处理函数地址。
| sysTid=1528 nice=0 cgrp=default sched=0/0 handle=0xb6f80de4
//state = native 线程状态 schedstat值来自于/proc/[pid]/task/[tid]/schedstat,分别是cpu上执行的时间、线程的等待时间和线程执行的时间片
// utm是线程用户态下执行时间 stm是内核态下执行时间(单位是jiffies) HZ可推出执行时间 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)
三、线程模型及线程状态
对于上述线程状态,相对于java线程状态,Linux细化了很多状态,这样更便于分析当前的状态。
java中的线程和操作系统内核中的线程并不是等价关系。他们之间存在着映射关系,对Android来说,java中的线程和内核的线程是一对一关系。