第一范文网 - 专业文章范例文档资料分享平台

ANR原因分析方法

来源:用户分享 时间:2025/5/30 23:53:13 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

// Dump thread traces as quickly as we can, starting with \ firstPids.add(app.pid);

//将父PID也放入firstPids集合 int parentPid = app.pid;

if (parent != null && parent.app != null && parent.app.pid > 0) parentPid =

parent.app.pid;

if (parentPid != app.pid) firstPids.add(parentPid);

//将主PID放入firstPids集合

if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);

//将persistent进程放入firstPids集合

for (int i = mLruProcesses.size() - 1; i >= 0; i--) { ProcessRecord r = mLruProcesses.get(i); if (r != null && r.thread != null) { int pid = r.pid;

if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) { if (r.persistent) {

firstPids.add(pid); } else {

lastPids.put(pid, Boolean.TRUE); } } } } }

// 将ANR信息写入log

// Log the ANR to the main log.

StringBuilder info = new StringBuilder(); info.setLength(0);

info.append(\

if (activity != null && activity.shortComponentName != null) {

info.append(\ }

info.append(\

info.append(\ if (annotation != null) {

info.append(\ }

if (parent != null && parent != activity) {

info.append(\ }

final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);

File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids, NATIVE_STACKS_OF_INTEREST);

String cpuInfo = null; if (MONITOR_CPU_USAGE) { updateCpuStatsNow();

synchronized (mProcessCpuThread) {

5

cpuInfo = mProcessCpuTracker.printCurrentState(anrTime); }

info.append(processCpuTracker.printCurrentLoad()); info.append(cpuInfo); }

info.append(processCpuTracker.printCurrentState(anrTime));

Slog.e(TAG, info.toString()); ...... }

AMS在发生ANR时,会按以下格式将ANR信息记录到logcat日志中:

ActivityManager: ANR in [Process Name]([short component name]) ActivityManager: PID: [Application Pid] ActivityManager: Reason: [Annotation]

ActivityManager: Parent: [short component name of parent] [Process CPU state]

其中的Reason信息可以给出ANR产生原因的一些详细信息,

? ? ?

输入事件处理引起的ANR,提示信息格式为:“Input dispatching timed out [anr reason]” Service处理引起的ANR,提示信息格式为:“Executing service [Package name]/[Short class name]”

Broadcast处理引起的ANR,提示信息格式为:“Broadcast of [Intent focused by Broadcast receiver]”

其中的Process CPU state 信息格式如下:

ActivityManager: Load: [Load1] / [Load5] / [Load15]

ActivityManager: CPU usage from [上次采样与现在的时间差] ms to [当前采样与现在的时间差] ms

ago/later:

ActivityManager: [总的CPU时间占用率]% [PID]/[Process Name]: [用户CPU时间占用率]% user + [系统

CPU时间占用率]% kernel + [IO等待CPU时间占用率]% iowait + [硬中断CPU时间占用率]% irq + [软中断CPU时间占用率]% softirq / faults: [次要页错误/主要页错误] minor/major

ActivityManager: .....

ActivityManager: [CPU时间占用率合计统计]

其中Load1, Load5, Load15分别为CPU 1分钟平均任务负载数,5分钟平均任务负载数,15分钟平均任务负载数,平均任务负载数和CPU占用率并没有必然联系,可以作为参考信息。可以通过分析各进程的CPU时间占用率,来判断是否为某些进程长期占用CPU导致该进程无法获取到足够的CPU处理时间,而导致发生ANR。 这里需要重点关注的是Load1,各进程总的CPU时间占用率,用户CPU时间占用率,系统CPU时间占用率,以及iowait CPU时间占用率。

2.2 通过trace文件分析原因

ActivityManagerService的appNotResponding方法在写入logcat日志的同时,还会将ANR时的stack trace信息写入到trace文件,具体代码流程如下:

final void appNotResponding(ProcessRecord app, ActivityRecord activity,

ActivityRecord parent, boolean aboveSystem, final String annotation) {

6

......

File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids, NATIVE_STACKS_OF_INTEREST); ...... }

public static File dumpStackTraces(boolean clearTraces, ArrayList firstPids, ProcessCpuTracker processCpuTracker, SparseArray lastPids, String[]

nativeProcs) {

//判断系统属性,确认trace文件路径

String tracesPath = SystemProperties.get(\ if (tracesPath == null || tracesPath.length() == 0) { return null; }

//若trace文件不存在则创建,并设置可读写属性 File tracesFile = new File(tracesPath); try {

File tracesDir = tracesFile.getParentFile(); if (!tracesDir.exists()) { tracesFile.mkdirs();

if (!SELinux.restorecon(tracesDir)) { return null; } }

FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x

if (clearTraces && tracesFile.exists()) tracesFile.delete(); tracesFile.createNewFile();

FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw- } catch (IOException e) {

Slog.w(TAG, \ return null; }

//执行dump操作

dumpStackTraces(tracesPath, firstPids, processCpuTracker, lastPids, nativeProcs); return tracesFile; }

private static void dumpStackTraces(String tracesPath, ArrayList firstPids, ProcessCpuTracker processCpuTracker, SparseArray lastPids, String[]

nativeProcs) {

//设置file observer

// Use a FileObserver to detect when traces finish writing.

// The order of traces is considered important to maintain for legibility.

FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) { @Override

public synchronized void onEvent(int event, String path) { notify(); } };

try {

observer.startWatching();

//向firstPids进程集合发送关闭信号,虚拟机接收到SIGNAL_QUIT信号后会将进程中各个线程的函//数堆栈信息输出到traces.txt文件中

// First collect all of the stacks of the most important pids.

7

if (firstPids != null) { try {

int num = firstPids.size();

for (int i = 0; i < num; i++) { synchronized (observer) {

Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);

observer.wait(200); // Wait for write-close, give up after 200msec } }

} catch (InterruptedException e) { Log.wtf(TAG, e); } }

// Next collect the stacks of the native pids if (nativeProcs != null) {

int[] pids = Process.getPidsForCommands(nativeProcs); if (pids != null) {

for (int pid : pids) {

Debug.dumpNativeBacktraceToFile(pid, tracesPath); } } }

//进行CPU占用率采样,并将占用率排在前几位的进程的stack trace信息dump到文件 // Lastly, measure CPU usage. if (processCpuTracker != null) { processCpuTracker.init(); System.gc();

processCpuTracker.update(); try {

synchronized (processCpuTracker) {

processCpuTracker.wait(500); // measure over 1/2 second. }

} catch (InterruptedException e) { }

processCpuTracker.update();

// We'll take the stack crawls of just the top apps using CPU. final int N = processCpuTracker.countWorkingStats(); int numProcs = 0;

for (int i=0; i

ProcessCpuTracker.Stats stats = processCpuTracker.getWorkingStats(i); if (lastPids.indexOfKey(stats.pid) >= 0) { numProcs++; try {

synchronized (observer) {

Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);

observer.wait(200); // Wait for write-close, give up after

200msec

}

} catch (InterruptedException e) { Log.wtf(TAG, e); }

8

搜索更多关于: ANR原因分析方法 的文档
ANR原因分析方法.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c2zmcb8302e0fvqv4zj28_2.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top