关键字:
当ANR不是发生在system server进程时,mian log会有关键字"ANR in”,如果anr发生在 system server进程,则main log一般不会记录到关键字"ANR in”
-->ProcessCpuTracker.java
final public String printCurrentLoad() {
StringWriter sw = new StringWriter();
PrintWriter pw = new FastPrintWriter(sw, false, 128);
pw.print("Load: ");
pw.print(mLoad1);
pw.print(" / ");
pw.print(mLoad5);
pw.print(" / ");
pw.println(mLoad15);
pw.flush();
return sw.toString();
}
final public String printCurrentState(long now) {
buildWorkingProcs();
StringWriter sw = new StringWriter();
PrintWriter pw = new FastPrintWriter(sw, false, 1024);
pw.print("CPU usage from ");
if (now > mLastSampleTime) {
pw.print(now-mLastSampleTime);
pw.print("ms to ");
pw.print(now-mCurrentSampleTime);
pw.print("ms ago");
} else {
pw.print(mLastSampleTime-now);
pw.print("ms to ");
pw.print(mCurrentSampleTime-now);
pw.print("ms later");
}
long sampleTime = mCurrentSampleTime - mLastSampleTime;
long sampleRealTime = mCurrentSampleRealTime - mLastSampleRealTime;
long percAwake = sampleRealTime > 0 ? ((sampleTime*100) / sampleRealTime) : 0;
if (percAwake != 100) {
pw.print(" with ");
pw.print(percAwake);
pw.print("% awake");
}
pw.println(":");
final int totalTime = mRelUserTime + mRelSystemTime + mRelIoWaitTime
+ mRelIrqTime + mRelSoftIrqTime + mRelIdleTime;
if (DEBUG) Slog.i(TAG, "totalTime " + totalTime + " over sample time "
+ (mCurrentSampleTime-mLastSampleTime));
int N = mWorkingProcs.size();
for (int i=0; i<N; i++) {
Stats st = mWorkingProcs.get(i);
printProcessCPU(pw, st.added ? " +" : (st.removed ? " -": " "),
st.pid, st.name, (int)st.rel_uptime,
st.rel_utime, st.rel_stime, 0, 0, 0, st.rel_minfaults, st.rel_majfaults);
if (!st.removed && st.workingThreads != null) {
int M = st.workingThreads.size();
for (int j=0; j<M; j++) {
Stats tst = st.workingThreads.get(j);
printProcessCPU(pw,
tst.added ? " +" : (tst.removed ? " -": " "),
tst.pid, tst.name, (int)st.rel_uptime,
tst.rel_utime, tst.rel_stime, 0, 0, 0, 0, 0);
}
}
}
printProcessCPU(pw, "", -1, "TOTAL", totalTime, mRelUserTime, mRelSystemTime,
mRelIoWaitTime, mRelIrqTime, mRelSoftIrqTime, 0, 0);
pw.flush();
return sw.toString();
}
private void printRatio(PrintWriter pw, long numerator, long denominator) {
long thousands = (numerator*1000)/denominator;
long hundreds = thousands/10;
pw.print(hundreds);
if (hundreds < 10) {
long remainder = thousands - (hundreds*10);
if (remainder != 0) {
pw.print('.');
pw.print(remainder);
}
}
}
private void printProcessCPU(PrintWriter pw, String prefix, int pid, String label,
int totalTime, int user, int system, int iowait, int irq, int softIrq,
int minFaults, int majFaults) {
pw.print(prefix);
if (totalTime == 0) totalTime = 1;
printRatio(pw, user+system+iowait+irq+softIrq, totalTime);
pw.print("% ");
if (pid >= 0) {
pw.print(pid);
pw.print("/");
}
pw.print(label);
pw.print(": ");
printRatio(pw, user, totalTime);
pw.print("% user + ");
printRatio(pw, system, totalTime);
pw.print("% kernel");
if (iowait > 0) {
pw.print(" + ");
printRatio(pw, iowait, totalTime);
pw.print("% iowait");
}
if (irq > 0) {
pw.print(" + ");
printRatio(pw, irq, totalTime);
pw.print("% irq");
}
if (softIrq > 0) {
pw.print(" + ");
printRatio(pw, softIrq, totalTime);
pw.print("% softirq");
}
if (minFaults > 0 || majFaults > 0) {
pw.print(" / faults:");
if (minFaults > 0) {
pw.print(" ");
pw.print(minFaults);
pw.print(" minor");
}
if (majFaults > 0) {
pw.print(" ");
pw.print(majFaults);
pw.print(" major");
}
}
pw.println();
}
事件派发超时ANR:
四 一些典型的ANR问题场景
4.1 最常见的错误,UI 线程等待其他线程释放某个锁,导致UI线程无处处理用户输入
4.2 游戏中每帧动画都进行了比较耗时的大量计算,导致CPU忙不过来
4.3 Web应用中,网络状态不稳定,而界面在等待网络数据
4.4 UI线程中进行了一些磁盘IO(包括数据库,SD卡等等)的耗时操作
4.5 手机被其他App占用着CPU,自己获取不到足够的CPU时间片
五 通过ANR日志定位问题
当ANR发生时,往往通过Logcat和traces文件(目录/data/anr)的相关信息输出来定位问题,主要包括以下几个方面:
5.1 基本信息,包括进程号名,进程号,包名,系统build号,ANR类型等等
5.2 CPU使用信息,包括活跃进程的CPU平均占用率,IO情况等
5.3 线程堆栈信息,所属进程包括发生ANR的进程,其父进程,最近有活动的3个进程等