1、ANR是什么

Application Not Responding即应用无响应。

当操作在一段时间内,系统无法处理是,就会发生ANR。弹出对应的无响应的对话框。

2、ANR的类型

发生ANR的主要是三种类型:

A)KeyDispatchTimeout

这个Key事件分发超时的时间,Android默认是5秒,主要是定义在ActivityManagerService.java

    // How long we wait until we timeout on key dispatching.    static final int KEY_DISPATCHING_TIMEOUT = 5*1000;

B)BroadcastTimeOut

广播的超时时间,分为FG和BG,分别是10秒和60秒。同样是定义在ActivitManagerService.java

    // How long we allow a receiver to run before giving up on it.    static final int BROADCAST_FG_TIMEOUT = 10*1000;    static final int BROADCAST_BG_TIMEOUT = 60*1000;

C)ServiceTimeOut

Service的超时时间为20秒,定义在ActiveServices.java

    // How long we wait for a service to finish executing.    static final int SERVICE_TIMEOUT = 20*1000;    // How long we wait for a service to finish executing.    static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

一般发生的ANR,大多都是KeyDispatchTimeout类型。

3、KeyDispatchTimeout是如何被触发的

   这个部分的code,主要是在InputDispatcher.cpp里面的handleTargetsNotReadyLocked()里面

int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,        const EventEntry* entry,        const sp& applicationHandle,        const sp& windowHandle,        nsecs_t* nextWakeupTime, const char* reason) {    if (applicationHandle == NULL && windowHandle == NULL) {        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {            ALOGD("Waiting for system to become ready for input.  Reason: %s", reason);            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;            mInputTargetWaitStartTime = currentTime;            mInputTargetWaitTimeoutTime = LONG_LONG_MAX;            mInputTargetWaitTimeoutExpired = false;            mInputTargetWaitApplicationHandle.clear();        }    } else {        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {            ALOGD("Waiting for application to become ready for input: %s.  Reason: %s",                    getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),                    reason);            nsecs_t timeout;            if (windowHandle != NULL) {                timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);            } else if (applicationHandle != NULL) {                timeout = applicationHandle->getDispatchingTimeout(                        DEFAULT_INPUT_DISPATCHING_TIMEOUT);            } else {                timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;            }            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;            mInputTargetWaitStartTime = currentTime;            mInputTargetWaitTimeoutTime = currentTime + timeout;            mInputTargetWaitTimeoutExpired = false;            mInputTargetWaitApplicationHandle.clear();            if (windowHandle != NULL) {                mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;            }            if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {                mInputTargetWaitApplicationHandle = applicationHandle;            }        }    }    if (mInputTargetWaitTimeoutExpired) {        return INPUT_EVENT_INJECTION_TIMED_OUT;    }    if (currentTime >= mInputTargetWaitTimeoutTime) {        onANRLocked(currentTime, applicationHandle, windowHandle,                entry->eventTime, mInputTargetWaitStartTime, reason);        // Force poll loop to wake up immediately on next iteration once we get the        // ANR response back from the policy.        *nextWakeupTime = LONG_LONG_MIN;        return INPUT_EVENT_INJECTION_PENDING;    } else {        // Force poll loop to wake up when timeout is due.        if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {            *nextWakeupTime = mInputTargetWaitTimeoutTime;        }        return INPUT_EVENT_INJECTION_PENDING;    }}

当applicationHandle == NULL 并且 windowHandle == NULL表示系统未启动完成。把状态设置为INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY

当系统启动完成后,先获取超时的时间,这个时间就是在AvtivityManagerservice.java中定义的

            if (windowHandle != NULL) {                timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);            } else if (applicationHandle != NULL) {                timeout = applicationHandle->getDispatchingTimeout(                        DEFAULT_INPUT_DISPATCHING_TIMEOUT);            } else {                timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;            }

然后把状态设置为INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,并且把超时的时间计算好。

            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;            mInputTargetWaitStartTime = currentTime;            mInputTargetWaitTimeoutTime = currentTime + timeout;            mInputTargetWaitTimeoutExpired = false;            mInputTargetWaitApplicationHandle.clear();

在下次事件过来的时候,再次去判断是否超过无响应的限制时间。如果超过就进行无响应的相关操作

    if (currentTime >= mInputTargetWaitTimeoutTime) {//超过无响应的时间限制        onANRLocked(currentTime, applicationHandle, windowHandle,                entry->eventTime, mInputTargetWaitStartTime, reason);        // Force poll loop to wake up immediately on next iteration once we get the        // ANR response back from the policy.        *nextWakeupTime = LONG_LONG_MIN;        return INPUT_EVENT_INJECTION_PENDING;    } 

4、当ANR发生了,ActivityManagerservice做了什么

主要是ActivityManagerservice.java的appNotResponding()

    final void appNotResponding(ProcessRecord app, ActivityRecord activity,            ActivityRecord parent, boolean aboveSystem, final String annotation) {ArrayList firstPids = new ArrayList(5);        SparseArray lastPids = new SparseArray(20);                if (mController != null) { // mController是IActivityController接口的实例,是为Monkey测试程序预留的,默认为null            try {                // 0 == continue, -1 = kill process immediately                int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);                if (res < 0 && app.pid != MY_PID) {                    app.kill("anr", true);                }            } catch (RemoteException e) {                mController = null;                Watchdog.getInstance().setActivityController(null);            }        }        long anrTime = SystemClock.uptimeMillis();        if (MONITOR_CPU_USAGE) {           // 更新CPU状态信息            updateCpuStatsNow();        }        synchronized (this) {            //系统关机、进程已经处于anr状态、crash状态,这些情况下忽略            // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.            if (mShuttingDown) {                Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);                return;            } else if (app.notResponding) {                Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);                return;            } else if (app.crashing) {                Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);                return;            }    //为了防止多次对相同app的anr执行重复代码,在此处标注记录            // In case we come through here for the same app before completing            // this one, mark as anring now so we will bail out.            app.notResponding = true;            // Log the ANR to the event log. 输出ANR信息到event log            EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,                    app.processName, app.info.flags, annotation);             // 添加当前app到firstpids列表中            // Dump thread traces as quickly as we can, starting with "interesting" processes.            firstPids.add(app.pid);    // 添加当前app的parentPid到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);            // 添加system_server到firstpids列表中            if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);//根据是否常驻内存分别添加到firstPids和lastPids            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信息存在info变量中,后续打印到LOGCAT,这部分的信息会以ActivityManager为Tag打印出来包含了ANR的进程,出现原因以及当时的CPU状态,这些对分析ANR是非常重要的信息*/        // Log the ANR to the main log.        StringBuilder info = new StringBuilder();        info.setLength(0);        info.append("ANR in ").append(app.processName);        if (activity != null && activity.shortComponentName != null) {            info.append(" (").append(activity.shortComponentName).append(")");        }        info.append("\n");        info.append("PID: ").append(app.pid).append("\n");        if (annotation != null) {            info.append("Reason: ").append(annotation).append("\n");        }        if (parent != null && parent != activity) {            info.append("Parent: ").append(parent.shortComponentName).append("\n");        }        final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);// 将ANR信息输出到traces文件        File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids,                NATIVE_STACKS_OF_INTEREST);        String cpuInfo = null;        if (MONITOR_CPU_USAGE) {    //再次获取CPU的信息            updateCpuStatsNow();            synchronized (mProcessCpuTracker) {                cpuInfo = mProcessCpuTracker.printCurrentState(anrTime);            }            info.append(processCpuTracker.printCurrentLoad());            info.append(cpuInfo);        }        info.append(processCpuTracker.printCurrentState(anrTime));//  输出到main log        Slog.e(TAG, info.toString());        if (tracesFile == null) {            // There is no trace file, so dump (only) the alleged culprit's threads to the log            Process.sendSignal(app.pid, Process.SIGNAL_QUIT);        }// 将ANR信息导入到DropBox目录下,也就是说除了traces文件还会有一个dropbox文件用于记录ANR        addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,                cpuInfo, tracesFile, null);        if (mController != null) {            try {                // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately                int res = mController.appNotResponding(app.processName, app.pid, info.toString());                if (res != 0) {                    if (res < 0 && app.pid != MY_PID) {                        app.kill("anr", true);                    } else {                        synchronized (this) {                            mServices.scheduleServiceTimeoutLocked(app);                        }                    }                    return;                }            } catch (RemoteException e) {                mController = null;                Watchdog.getInstance().setActivityController(null);            }        }        // Unless configured otherwise, swallow ANRs in background processes & kill the process.        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;        synchronized (this) {             //主动通知battery state service,发生了ANR            mBatteryStatsService.noteProcessAnr(app.processName, app.uid);            if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {                app.kill("bg anr", true);                return;            }            // Set the app's notResponding state, and look up the errorReportReceiver            makeAppNotRespondingLocked(app,                    activity != null ? activity.shortComponentName : null,                    annotation != null ? "ANR " + annotation : "ANR",                    info.toString());//弹出无响应的对话框            // Bring up the infamous App Not Responding dialog            Message msg = Message.obtain();            HashMap map = new HashMap();            msg.what = SHOW_NOT_RESPONDING_MSG;            msg.obj = map;            msg.arg1 = aboveSystem ? 1 : 0;            map.put("app", app);            if (activity != null) {                map.put("activity", activity);            }            mHandler.sendMessage(msg);        }    }

   主要是dump相关的信息到traces文件里面File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids, NATIVE_STACKS_OF_INTEREST);

输出main log信息  Slog.e(TAG, info.toString());

发生ANR的信息导入到dropbox目录下  addErrorToDropBox("anr", app, app.processName, activity, parent, annotation, cpuInfo, tracesFile, null);

最后根据条件,来判断是否要弹出无响应的对话框。

4、如何根据log来分析ANR

4.1 一般要先分析Main log

  a)    先在Main log里面搜索关键字 “ANR”,确定是否真的有发生ANR。

  b) 查看在ANR之前,系统是否发生了JE(Java Exception)或者NE(Native Exception),有时候一些ANR是由JE或者NE引起的。

  c)  在发生ANR的地方,查看对应的log信息。

        例如:

05-01 23:03:24.603 E/ActivityManagerService( 1573): ANR in com.tpv.xmic.contentbrowser.ebony2k15 (com.tpv.xmic.contentbrowser.ebony2k15/com.tpv.xmic.mediacenter.player.videoplayer.VideoPlayerActivity)05-01 23:03:24.603 E/ActivityManagerService( 1573): PID: 310905-01 23:03:24.603 E/ActivityManagerService( 1573): Reason: Input dispatching timed out (Waiting to send key event because the focused window has not finished processing all of the input events that were previously delivered to it.  Outbound queue length: 0.  Wait queue length: 1.)05-01 23:03:24.603 E/ActivityManagerService( 1573): Load: 6.44 / 5.38 / 5.0705-01 23:03:24.603 E/ActivityManagerService( 1573): CPU usage from 0ms to 8532ms later:05-01 23:03:24.603 E/ActivityManagerService( 1573):   52% 1165/logd: 50% user + 2.4% kernel / faults: 2 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   35% 1573/system_server: 13% user + 21% kernel / faults: 9349 minor 58 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   13% 1193/tvos: 8.5% user + 4.5% kernel / faults: 1 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   11% 1176/mediaserver: 5.9% user + 5.2% kernel / faults: 317 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   8.6% 3137/com.tpv.xmic.contentbrowser.ebony2k15:MediaScanService: 4.9% user + 3.7% kernel / faults: 2340 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   4.2% 3109/com.tpv.xmic.contentbrowser.ebony2k15: 2.9% user + 1.2% kernel / faults: 3049 minor 72 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   6.4% 1170/surfaceflinger: 4.2% user + 2.2% kernel / faults: 129 minor 1 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   6.4% 17981/ntfs-3g: 2.6% user + 3.7% kernel / faults: 157 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   5.9% 2624/com.mstar.android.providers.tv: 3.6% user + 2.3% kernel / faults: 3514 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   5.8% 1783/com.android.systemui: 2.6% user + 3.1% kernel / faults: 3578 minor 4 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   3.1% 1806/com.mstar.tv.service: 1.6% user + 1.4% kernel / faults: 3161 minor 2 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 1174/debuggerd64: 0% user + 0% kernel / faults: 5068 minor 11 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2458/com.tpv.contextualSetting: 0% user + 0% kernel / faults: 3146 minor 1 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.2% 2386/com.ktcp.autoupgrade: 0.1% user + 0% kernel / faults: 2423 minor 1 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   1.8% 2302/org.droidtv.dlna: 0.9% user + 0.9% kernel / faults: 2193 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2440/com.tpv.functionadjust: 0% user + 0% kernel / faults: 1841 minor 1 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2147/com.tpv.bluetooth: 0% user + 0% kernel / faults: 1854 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2168/com.tpv.setting: 0% user + 0% kernel / faults: 2254 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2366/com.xmic.screenmirror: 0% user + 0% kernel / faults: 2468 minor 9 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2422/com.tpv.xmic.smartrc.ots2k15: 0% user + 0% kernel / faults: 1835 minor 4 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2199/com.tpv.xmic.smartrc.ebony2k14: 0% user + 0% kernel / faults: 2221 minor 23 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2323/com.tpv.xmic.ap: 0% user + 0% kernel / faults: 2297 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   1% 2404/com.tpv.xmic.recordersreminders.ebony2k15: 0.4% user + 0.6% kernel / faults: 2172 minor 13 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   2.4% 3400/mstar.tvsetting.factory.ui: 1.4% user + 1% kernel / faults: 1699 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2251/com.tpv.xmic.dbcservice: 0% user + 0% kernel / faults: 1873 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2348/com.redbend.client: 0% user + 0% kernel / faults: 2026 minor 7 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2276/com.mstar.android.pppoe: 0% user + 0% kernel / faults: 2276 minor 3 major05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 1710/android.process.media: 0% user + 0% kernel / faults: 1957 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2067/com.xmic.voice: 0% user + 0% kernel / faults: 1903 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2108/com.tpv.ebony2K15_AppSource: 0% user + 0% kernel / faults: 1914 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   1.4% 17957/usb-storage: 0% user + 1.4% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   1.2% 682/mmcqd/0: 0% user + 1.2% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2221/com.tpv.xmic.dlna.dmr: 0% user + 0% kernel / faults: 2032 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.5% 3361/logcat: 0.1% user + 0.4% kernel / faults: 2 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.4% 16087/kworker/0:0: 0% user + 0.4% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.3% 1181/livecap: 0.2% user + 0.1% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 3/ksoftirqd/0: 0% user + 0.1% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 12/ksoftirqd/1: 0% user + 0.1% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 319/ion_system_heap: 0% user + 0.1% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.2% 1142/jbd2/mmcblk0p14: 0% user + 0.2% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.2% 1190/adbd: 0% user + 0.2% kernel / faults: 102 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 8/rcu_preempt: 0% user + 0% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 1180/virtualkeypad: 0% user + 0% kernel / faults: 1 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 1953/com.android.inputmethod.pinyin: 0% user + 0% kernel / faults: 3 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2773/mstar.tvsetting.factory.ui:remote: 0% user + 0% kernel / faults: 1 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 3286/RTW_CMD_THREAD: 0% user + 0% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 3309/com.tpv.ebony2k15.joystick: 0% user + 0% kernel / faults: 5 minor05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 16074/kworker/2:1: 0% user + 0.1% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 17662/kworker/1:0: 0% user + 0% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 17796/kworker/1:1: 0% user + 0% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573):  +0% 18070/kworker/3:0: 0% user + 0% kernel05-01 23:03:24.603 E/ActivityManagerService( 1573): 73% TOTAL: 35% user + 25% kernel + 12% iowait + 0%

 如上的log信息,解读如下:

发生ANR的时间为 05-01 23:03:24.603

对应的进程为 com.tpv.xmic.contentbrowser.ebony2k15

ANR的进程号为PID: 3109

ANR的原因为  Input dispatching timed out

发生ANR后的CPU信息:

05-01 23:03:24.603 E/ActivityManagerService( 1573): CPU usage from 0ms to 8532ms later:05-01 23:03:24.603 E/ActivityManagerService( 1573):   52% 1165/logd: 50% user + 2.4% kernel / faults: 2 minor...05-01 23:03:24.603 E/ActivityManagerService( 1573): 73% TOTAL: 35% user + 25% kernel + 12% iowait + 0%

根据现有的log信息还是无法确定ANR的根源。需要进一步的去分析对应的traces文件。

main log里面的ANR输出格式大致如下

ActivityManager: ANR in [Process Name]([short component name]) ActivityManager: PID: [Process Pid] ActivityManager: Reason: [Annotation]  ActivityManager: Parent: [short component name of parent] 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时间占用率合计统计]

有时候main log里面的cpu相关信息就可以大致确定ANR的原因,例如JE、 NE、  CPU  100% 等等


4.2 Traces文件的分析

一个Traces文件,不同的系统有差异,格式大致如下:

----- pid 3109 at 2015-05-01 23:03:16 -----Cmd line: com.tpv.xmic.contentbrowser.ebony2k15ABI: armBuild type: optimizedLoaded classes: 4083 allocated classesIntern table: 5645 strong; 1324 weakJNI: CheckJNI is on; globals=330 (plus 1 weak)Heap: 17% free, 29MB/35MB; 221169 objectsDumping cumulative Gc timingsStart Dumping histograms for 47 iterations for concurrent mark sweep...Total time spent in GC: 4.653sMean GC size throughput: 15MB/sMean GC object throughput: 264330 objects/sTotal number of allocations 1451323Total bytes allocated 103MBFree memory 6MBFree memory until GC 6MBFree memory until OOME 226MBTotal memory 35MBMax memory 256MBTotal mutator paused time: 380.545msTotal time waiting for GC to complete: 247.672usDALVIK THREADS (30):"main" prio=5 tid=1 Native  | group="main" sCount=1 dsCount=0 obj=0x74a26ff8 self=0xf5007800  | sysTid=3109 nice=0 cgrp=apps sched=0/0 handle=0xf7701ec8  | state=S schedstat=( 0 0 0 ) utm=4101 stm=537 core=0 HZ=100  | stack=0xff6fa000-0xff6fc000 stackSize=8MB  | held mutexes=  kernel: __switch_to+0x74/0x8c  kernel: binder_thread_read+0x8a8/0x1004  kernel: binder_ioctl+0x6b0/0x97c  kernel: compat_sys_ioctl+0xb0/0x15c8  kernel: el0_svc_naked+0x34/0x38  native: #00 pc 00039ae8  /system/lib/libc.so (__ioctl+8)  native: #01 pc 00051b9d  /system/lib/libc.so (ioctl+14)  native: #02 pc 0001f3e7  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+190)  native: #03 pc 0001fa5b  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+42)  native: #04 pc 0001fc1d  /system/lib/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+124)  native: #05 pc 0001ad47  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+30)  native: #06 pc 000629ff  /system/lib/libmedia.so (???)  native: #07 pc 0005f757  /system/lib/libmedia.so (android::MediaPlayer::disconnect()+46)  native: #08 pc 0001ef5d  /system/lib/libmedia_jni.so (???)  native: #09 pc 000058d3  /data/dalvik-cache/arm/[email protected]@boot.oat (Java_android_media_MediaPlayer__1release__+82)  at android.media.MediaPlayer._release(Native method)  at android.media.MediaPlayer.release(MediaPlayer.java:1472)  ...  at android.view.KeyEvent.dispatch(KeyEvent.java:2617)  at android.app.Activity.dispatchKeyEvent(Activity.java:2720)  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2737)  at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4098)  at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4060)  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3629)  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3682)  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3648)  at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3758)  at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3656)  at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3815)  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3629)  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3682)  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3648)  at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3656)  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3629)  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3682)  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3648)  at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3791)  at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3952)  at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2208)  at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1849)  at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1840)  at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2185)  at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)  at android.os.MessageQueue.nativePollOnce(Native method)  at android.os.MessageQueue.next(MessageQueue.java:143)  at android.os.Looper.loop(Looper.java:122)  at android.app.ActivityThread.main(ActivityThread.java:5409)  at java.lang.reflect.Method.invoke!(Native method)  at java.lang.reflect.Method.invoke(Method.java:372)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:902)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:697)

a)Traces文件里面的相关信息要和main log对应上,才能确保是同一个问题

----- pid 3109 at 2015-05-01 23:03:16 -----Cmd line: com.tpv.xmic.contentbrowser.ebony2k15

这里的pid为3109 ,时间为2015-05-01 23:03:16,进程名为com.tpv.xmic.contentbrowser.ebony2k15。

和mainlog是 一 一对应的,说明是发生ANR对应的traces文件。

b)这个问题的trace文件里面描述的清楚,主要发生ANR的原因在于内存过低,不停的GC

Free memory 6MB

c)当然trace里面的相关信息,也有必要做一下解读。

DALVIK THREADS (30):"main" prio=5 tid=1 Native  | group="main" sCount=1 dsCount=0 obj=0x74a26ff8 self=0xf5007800  | sysTid=3109 nice=0 cgrp=apps sched=0/0 handle=0xf7701ec8  | state=S schedstat=( 0 0 0 ) utm=4101 stm=537 core=0 HZ=100  | stack=0xff6fa000-0xff6fc000 stackSize=8MB  | held mutexes=

第1行:

DALVIK THREADS这个是固定的格式,指明下面都是当前运行的dalvik threads

第2行:

main为当前线程的名字,(有的线程后面会有daemon,表示为守护进程)

prio表示为优先级,默认值为5

tid表示为thread id,tid为1表示为正在运行的thread

Native表示为线程的状态。线程的状态都是定义在Thread.cpp里面的。具体如下表

Android ANR简介_第1张图片

第3行:

线程组的名字:group =“main”

sCount =1,(suspend cound)表示线程被挂起的次数为1次

dsCount =0,(debug suspend count)表示线程被调试挂起的次数为0

obj=0x74a26ff8,这个是线程的java对象的地址

self=0xf5007800,这个是线程本身的地址

第4行:

sysTid=3109,线程在linux系统下得本地线程id (sysTid和PID相同)

nice=0, 这个是线程的调度优先级

cgrp=apps ,这个是线程调度所属的组。

sched=0/0,线程调度的策略

handle= 0xf7701ec8,处理函数地址。

第5行:

state=S, 是调度状态

schedstat=( 0  0 0 ),这个是从 /proc/[pid]/task/[tid]/schedstat读出,三个值分别表示线程在cpu上执行的时间、线程的等待时间和线程执行的时间片长度。有的android内核版本不支持这项信息,得到的三个值都是0

utm=4101,线程用户态下使用的时间值( 单位是jiffies)。

stm=573,内核态下得调度时间值(单位是jiffies)。

core=0,最后运行该线程的cup序号,即序号为0的CPU运行该线程。

第6行:

stack=0xff6fa000-0xff6fc000,表示线程栈地址范围

stackSize=8MB,表示线程栈的大小为8M。通过(0xff6fc000-0xff6fa000 = 0x2000=8M)计算得到

d)接下来就是函数的调用堆栈了。

这个部分,有时候进一步分析ANR的具体原因的时候,需要进一步去看对应的 source code。通过调用堆栈可以快递定位到对应的文件和函数。

 kernel: __switch_to+0x74/0x8c  kernel: binder_thread_read+0x8a8/0x1004  kernel: binder_ioctl+0x6b0/0x97c  kernel: compat_sys_ioctl+0xb0/0x15c8  kernel: el0_svc_naked+0x34/0x38  native: #00 pc 00039ae8  /system/lib/libc.so (__ioctl+8)  native: #01 pc 00051b9d  /system/lib/libc.so (ioctl+14)  native: #02 pc 0001f3e7  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+190)  native: #03 pc 0001fa5b  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+42)  native: #04 pc 0001fc1d  /system/lib/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+124)  native: #05 pc 0001ad47  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+30)  native: #06 pc 000629ff  /system/lib/libmedia.so (???)  native: #07 pc 0005f757  /system/lib/libmedia.so (android::MediaPlayer::disconnect()+46)  native: #08 pc 0001ef5d  /system/lib/libmedia_jni.so (???)  native: #09 pc 000058d3  /data/dalvik-cache/arm/syst[email protected]@boot.oat (Java_android_media_MediaPlayer__1release__+82)  at android.media.MediaPlayer._release(Native method)  at android.media.MediaPlayer.release(MediaPlayer.java:1472)  ...  at android.view.KeyEvent.dispatch(KeyEvent.java:2617)  at android.app.Activity.dispatchKeyEvent(Activity.java:2720)

例如:

at android.media.MediaPlayer.release(MediaPlayer.java:1472)

表示对应的包名为android.media.MediaPlayer的release()函数。

文件名为MediaPlayer.java的第1472行。


一般来说Trace文件顶部的线程是ANR的元凶。这里只是举一个例子。

当然,发生ANR的原因各不同,需要根据具体的问题做具体的分析。


5、如何避免AR呢

与其事后来解决ANR的问题,不如在开发的过程中多注意,避免发生ANR。

总结一些需要注意的实现如下:

a)UI主线程尽量只做跟UI相关的工作.

b) 耗时的操作,如I/O,网络连接,把它放入单独的线程处理

c) 尽量用Handler来处理UI线程和非UI线程之间的交互


更多相关文章

  1. android 多线程数据库读写分析与优化
  2. Android 开启新线程
  3. Android多线程分析之三:Handler,Looper的实现
  4. Android的UI主线程和子线程
  5. Android系统信息获取 之五:系统语言信息(续)-语言地区和简写对照表
  6. 1.活用Android线程间通信的Message机制
  7. Android 设备屏幕信息(dip,sp,px的转换及其运用)

随机推荐

  1. 【Android】定义HttpPost连接超时
  2. android 自定义组件随着手指自动画圆
  3. android中opengl es基本方法使用说明
  4. Android(安卓)文件操作
  5. android中操作SQLite常见错误
  6. android canmera相机
  7. windows下搭建cocos2dx Android开发环境
  8. Android(安卓)TimeLine 时间节点轴的实现
  9. android 处理图片的工具类
  10. Android(安卓)全面屏的和有导航栏的判断