性能优化最佳实践#ANR

75 阅读22分钟

性能优化最佳实践#启动优化

性能优化最佳实践#UI卡顿优化

性能优化最佳实践#内存优化

性能优化最佳实践#Crash机制

性能优化最佳实践#ANR优化

性能优化最佳实践#体积包优化

一.定义与产生机制

1.定义

ANR是ApplicationNotResponse简称,是指应用程序在一定的时间内响应未完成或响应时间过长,由此产生的ANR,它是发生在主线程中。

2.产生机制

我们知道Android基于事件驱动,ANR也是基于主线程的Looper机制,在事件触发前,发起一个延迟消息,然后会在特定的位置移除这个消息,如果未能移除就会报ANR,以下就是触发机制的流程,基本上可以概括为,预埋点,移除预埋点,如果未能移除就会报错,相关Service、BroadCastReceive等埋点和移除可以自行查看下源码,但是流程可以概括如下:

二.ANR分类

1.常见的ANR

    • 点击事件(Input event dispatching time out ):超过5秒未响应; - Service( Timeout excuting service):前台20秒,后台200秒服务未启动完成; - BroadcastReceiver(Timeout of broadcast receiver):前台10秒,后台60秒,未处理完onReceiver中的代码; - contentProvider(Timeout publishing content providers):publish在10秒内未处理完。

2.其他的ANR

    • Binder导致的:Binder通讯数据量过大、Binder线程池过多,超过15个; - 线程阻塞或死锁; - 频繁GC导致的事件处理过长。

三.定位与分析

1.日志文件定位

发生anr后日志会被保存在data/anr中,在 traces.txt 找到发生 ANR 时间节点、主线程的状态、ANR 类型和事故点。

2.日志过滤定位

logcat-v time打印mainlog,在 mainlog 日志查看 CPU 状态,根据以上步骤收集的信息大致判断问题原因是 CPU 问题还是 非 CPU 问题,如果是非 CPU 问题,那么看 GC 处理信息,在 traces.txt 分析 CG 信息,结合项目代码和以上步骤分析到的原因,定位到问题修复 ANR。
线程状态:

3.样例分析

1.点击事件超时分析

我们从日志里得到anr事件类型、PID、CPU使用状况:

class MainActivity:AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }

    fun anrTest(view: View) {
        Thread.sleep(6*1000)
    }
}

1.日志打印:

07-23 07:44:43.621 I/ActivityManager(  535): Done dumping
07-23 07:44:43.622 E/ActivityManager(  535): ANR in com.seven.anr (com.seven.anr/.MainActivity)
07-23 07:44:43.622 E/ActivityManager(  535): PID: 29965
07-23 07:44:43.622 E/ActivityManager(  535): Reason: Input dispatching timed out (3a76ec7 com.seven.anr/com.seven.anr.MainActivity (server) is not responding. Waited 5003ms for KeyEvent(deviceId=0, source=0x00000301, displayId=-1, action=DOWN, flags=0x00000008, keyCode=4, scanCode=158, metaState=0x00000000, repeatCount=0), policyFlags=0x62000000)
07-23 07:44:43.622 E/ActivityManager(  535): Parent: com.seven.anr/.MainActivity
07-23 07:44:43.622 E/ActivityManager(  535): Load: 0.2 / 0.15 / 0.13
07-23 07:44:43.622 E/ActivityManager(  535): ----- Output from /proc/pressure/memory -----
07-23 07:44:43.622 E/ActivityManager(  535): some avg10=0.00 avg60=0.00 avg300=0.00 total=0
07-23 07:44:43.622 E/ActivityManager(  535): full avg10=0.00 avg60=0.00 avg300=0.00 total=0
07-23 07:44:43.622 E/ActivityManager(  535): ----- End output from /proc/pressure/memory -----
07-23 07:44:43.622 E/ActivityManager(  535):
07-23 07:44:43.622 E/ActivityManager(  535): CPU usage from 128501ms to 0ms ago (2025-07-23 07:42:33.813 to 2025-07-23 07:44:42.314):
07-23 07:44:43.622 E/ActivityManager(  535):   3.1% 293/android.hardware.bluetooth@1.1-service.sim: 0% user + 3.1% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   2.3% 303/android.hardware.graphics.composer@2.3-service: 0% user + 2.3% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   2% 27831/transport: 0% user + 1.9% kernel / faults: 27 minor
07-23 07:44:43.622 E/ActivityManager(  535):   1.9% 535/system_server: 0% user + 1.8% kernel / faults: 14933 minor
07-23 07:44:43.622 E/ActivityManager(  535):   1.7% 173/logd: 0% user + 1.7% kernel / faults: 10 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0.7% 324/surfaceflinger: 0% user + 0.7% kernel / faults: 115 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0.6% 311/android.hardware.sensors@2.1-service.multihal: 0% user + 0.6% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 1076/com.android.launcher3: 0% user + 0% kernel / faults: 340 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 302/android.hardware.graphics.allocator@3.0-service: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0.2% 372/adbd: 0% user + 0.2% kernel / faults: 708 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0.2% 29823/com.seven.memory: 0% user + 0.2% kernel / faults: 2008 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0.1% 26/ksoftirqd/3: 0% user + 0.1% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0.1% 700/com.android.systemui: 0% user + 0.1% kernel / faults: 74 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 291/android.hardware.audio.service.ranchu: 0% user + 0% kernel / faults: 10 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0.1% 10/rcu_preempt: 0% user + 0.1% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0.1% 917/com.android.phone: 0% user + 0.1% kernel / faults: 253 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0.1% 1894/com.android.permissioncontroller: 0% user + 0.1% kernel / faults: 821 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 420/audioserver: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 26886/process-tracker: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 27694/process-tracker: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 16/ksoftirqd/1: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 379/traced_probes: 0% user + 0% kernel / faults: 2 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 402/llkd: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 9/ksoftirqd/0: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 27685/logcat: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 205/jbd2/dm-5-8: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 785/android.hardware.gnss@2.0-service.ranchu: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 29796/kworker/3:2-events_power_efficient: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 31/kauditd: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 286/statsd: 0% user + 0% kernel / faults: 4 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 388/iorapd: 0% user + 0% kernel / faults: 71 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 29535/kworker/0:1-mm_percpu_wq: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 29904/kworker/u8:2-events_unbound: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 21/ksoftirqd/2: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 142/kworker/1:1H-kblockd: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 175/servicemanager: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 287/netd: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 288/zygote64: 0% user + 0% kernel / faults: 173 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 304/android.hardware.health@2.1-service: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 380/traced: 0% user + 0% kernel / faults: 20 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 394/wificond: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 396/libgoldfish-rild: 0% user + 0% kernel / faults: 14 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 401/android.hardware.biometrics.fingerprint@2.1-service: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 426/netmgr: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 430/hostapd_nohidl: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 676/wpa_supplicant: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 1268/com.android.inputmethod.latin: 0% user + 0% kernel / faults: 1 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 4208/com.android.packageinstaller: 0% user + 0% kernel / faults: 2 minor
07-23 07:44:43.622 E/ActivityManager(  535):   0% 29253/kworker/1:3-events: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   0% 29869/kworker/u8:1-events_unbound: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):  +0% 29965/com.seven.anr: 0% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535): 2.5% TOTAL: 0% user + 2.5% kernel + 0% iowait
07-23 07:44:43.622 E/ActivityManager(  535): CPU usage from 22ms to 303ms later (2025-07-23 07:44:42.336 to 2025-07-23 07:44:42.617):
07-23 07:44:43.622 E/ActivityManager(  535):   53% 1076/com.android.launcher3: 0% user + 53% kernel / faults: 40 minor
07-23 07:44:43.622 E/ActivityManager(  535):     44% 1497/RenderThread: 0% user + 44% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     8.8% 1076/droid.launcher3: 0% user + 8.8% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.4% 1121/UiThreadHelper: 0% user + 4.4% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.4% 1122/launcher-loader: 0% user + 4.4% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   40% 303/android.hardware.graphics.composer@2.3-service: 0% user + 40% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     40% 303/composer@2.3-se: 0% user + 40% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4% 354/: 0% user + 4% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   24% 324/surfaceflinger: 0% user + 24% kernel / faults: 15 minor
07-23 07:44:43.622 E/ActivityManager(  535):     8.2% 324/surfaceflinger: 0% user + 8.2% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.1% 435/surfaceflinger: 0% user + 4.1% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.1% 454/app: 0% user + 4.1% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.1% 1228/Binder:324_5: 0% user + 4.1% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   25% 535/system_server: 0% user + 25% kernel / faults: 251 minor
07-23 07:44:43.622 E/ActivityManager(  535):     12% 30010/AnrConsumer: 0% user + 12% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.2% 553/android.ui: 4.2% user + 0% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.2% 4969/Binder:535_1F: 0% user + 4.2% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   25% 700/com.android.systemui: 4.2% user + 21% kernel / faults: 433 minor
07-23 07:44:43.622 E/ActivityManager(  535):     8.5% 1189/RenderThread: 0% user + 8.5% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.2% 700/ndroid.systemui: 0% user + 4.2% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.2% 716/HeapTaskDaemon: 0% user + 4.2% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.2% 719/FinalizerDaemon: 0% user + 4.2% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   18% 29965/com.seven.anr: 0% user + 18% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     14% 29987/RenderThread: 0% user + 14% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   12% 302/android.hardware.graphics.allocator@3.0-service: 0% user + 12% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     12% 349/HwBinder:302_2: 0% user + 12% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   7.3% 173/logd: 0% user + 7.3% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     7.3% 187/logd.auditd: 0% user + 7.3% kernel
07-23 07:44:43.622 E/ActivityManager(  535):   4.6% 27831/transport: 0% user + 4.6% kernel
07-23 07:44:43.622 E/ActivityManager(  535):     4.6% 27843/DetectPable: 0% user + 4.6% kernel
07-23 07:44:43.622 E/ActivityManager(  535): 58% TOTAL: 3% user + 53% kernel + 1% iowait + 1% softirq
07-23 07:44:43.622 I/ActivityManager(  535): Killing 29965:com.seven.anr/u0a150 (adj 900): bg anr
07-23 07:44:43.623 D/ActivityManager(  535): Completed ANR of com.seven.anr in 1309ms, latency 0ms
07-23 07:44:43.625 I/DropBoxManagerService(  535): add tag=data_app_anr isTagEnabled=true flags=0x2
07-23 07:44:43.647 I/Zygote  (  288): Process 29965 exited due to signal 9 (Killed)
07-23 07:44:43.673 I/libprocessgroup(  535): Successfully killed process cgroup uid 10150 pid 29965 in 50ms
07-23 07:44:44.526 W/audit   (    0): audit_lost=519121 audit_rate_limit=5 audit_backlog_limit=64

如果某些进程的 CPU 占用百分比较高,几乎占用了所有 CPU 资源,而发生 ANR 的进程(一般说的是我们的 app 进程)CPU 占用为 0% 或非常低,则认为 CPU 资源被占用,app 进程没有被分配足够的资源,从而发生了 ANR。这种情况多数可以认为是系统状态的问题,并不是由应用造成的(简单讲就是其他进程 CPU 使用率非常高自己低,就是系统资源分配不足导致)。如果发生 ANR 的进程(一般说的是我们的 app 进程)CPU 占用较高,如到了 80% 或 90% 以上,则可以怀疑应用内一些代码不合理消耗掉了 CPU 资源,如出现了死循环或者后台有许多线程执行任务等等原因,这就要结合 traces.txt 和 ANR 前后的 mainlog 日志进一步分析(简单理解就是 IO 非常频繁,要么死循环了,要么上锁了)如果 CPU 总用量不高,该进程和其他进程的占用过高,这有一定概率是由于某些主线程的操作就是耗时过长,或者是由于主进程被锁造成的。

2.从traces.txt查看具体主线程状态

"main" prio=5 tid=1 Sleeping
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x72d6f188 self=0x7257818be010
  | sysTid=30219 nice=-10 cgrp=top-app sched=0/0 handle=0x7258a779a4f8
  | state=S schedstat=( 685524155 62491498 380 ) utm=22 stm=45 core=1 HZ=100
  | stack=0x7ffd6e674000-0x7ffd6e676000 stackSize=8192KB
  | held mutexes=
  at java.lang.Thread.sleep(Native method)
  - sleeping on <0x00004564> (a java.lang.Object)
  at java.lang.Thread.sleep(Thread.java:442)
  - locked <0x00004564> (a java.lang.Object)
  at java.lang.Thread.sleep(Thread.java:358)
  at com.seven.anr.MainActivity.anrTest(MainActivity.kt:25)
  at java.lang.reflect.Method.invoke(Native method)
  at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:468)
  at android.view.View.performClick(View.java:7448)
  at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1202)
  at android.view.View.performClickInternal(View.java:7425)
  at android.view.View.access$3600(View.java:810)
  at android.view.View$PerformClick.run(View.java:28305)
  at android.os.Handler.handleCallback(Handler.java:938)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loop(Looper.java:223)
  at android.app.ActivityThread.main(ActivityThread.java:7656)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

2.同步锁样例分析

//    一段由synchronized锁引起的anr,子线程调用主线程的同步方法,
//    由于testAnr和initView是同一个锁,这样主线程和子线程抢占同步锁,导致了anr。
    fun deadLock(view: View) {

        Thread {
            testAnr()
        }.start()

        try {
            Thread.sleep(1000)
        } catch (e: InterruptedException) {
            e.printStackTrace();
        }
        //一直在等待锁
        initView()
    }


    @Synchronized
    private fun testAnr() {
        println("can run anr")
        //一直没有释放锁
        SystemClock.sleep((30 * 1000).toLong())
    }

    @Synchronized
    private fun initView() {
        println("can run init")
    }
}

1.日志打印


07-23 08:06:46.240 E/ActivityManager(  535): ANR in com.seven.anr (com.seven.anr/.MainActivity)
07-23 08:06:46.240 E/ActivityManager(  535): PID: 30467
07-23 08:06:46.240 E/ActivityManager(  535): Reason: Input dispatching timed out (d16d452 com.seven.anr/com.seven.anr.MainActivity (server) is not responding. Waited 5002ms for MotionEvent(deviceId=11, source=0x00005002, displayId=0, action=DOWN, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=68.3, yPrecision=41.0, xCursorPosition=nan, yCursorPosition=nan, pointers=[0: (282.0, 326.0)]), policyFlags=0x62000000)
07-23 08:06:46.240 E/ActivityManager(  535): Parent: com.seven.anr/.MainActivity
07-23 08:06:46.240 E/ActivityManager(  535): Load: 0.13 / 0.11 / 0.12
07-23 08:06:46.240 E/ActivityManager(  535): ----- Output from /proc/pressure/memory -----
07-23 08:06:46.240 E/ActivityManager(  535): some avg10=0.00 avg60=0.00 avg300=0.00 total=0
07-23 08:06:46.240 E/ActivityManager(  535): full avg10=0.00 avg60=0.00 avg300=0.00 total=0
07-23 08:06:46.240 E/ActivityManager(  535): ----- End output from /proc/pressure/memory -----
07-23 08:06:46.240 E/ActivityManager(  535):
07-23 08:06:46.240 E/ActivityManager(  535): CPU usage from 251334ms to 0ms ago (2025-07-23 08:02:33.912 to 2025-07-23 08:06:45.246):
07-23 08:06:46.240 E/ActivityManager(  535):   3.8% 293/android.hardware.bluetooth@1.1-service.sim: 0% user + 3.7% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   2.2% 27831/transport: 0% user + 2.1% kernel / faults: 123 minor
07-23 08:06:46.240 E/ActivityManager(  535):   1.8% 173/logd: 0% user + 1.8% kernel / faults: 38 minor
07-23 08:06:46.240 E/ActivityManager(  535):   1.5% 303/android.hardware.graphics.composer@2.3-service: 0% user + 1.5% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   1.1% 535/system_server: 0% user + 1% kernel / faults: 6016 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0.7% 311/android.hardware.sensors@2.1-service.multihal: 0% user + 0.7% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0.2% 372/adbd: 0% user + 0.2% kernel / faults: 1527 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0.2% 324/surfaceflinger: 0% user + 0.2% kernel / faults: 168 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0.1% 917/com.android.phone: 0% user + 0.1% kernel / faults: 319 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0.1% 26886/process-tracker: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0.1% 10/rcu_preempt: 0% user + 0.1% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 291/android.hardware.audio.service.ranchu: 0% user + 0% kernel / faults: 15 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0.1% 700/com.android.systemui: 0% user + 0.1% kernel / faults: 113 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0.1% 27694/process-tracker: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 29823/com.seven.memory: 0% user + 0% kernel / faults: 48 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 302/android.hardware.graphics.allocator@3.0-service: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 1076/com.android.launcher3: 0% user + 0% kernel / faults: 558 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 1894/com.android.permissioncontroller: 0% user + 0% kernel / faults: 731 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 420/audioserver: 0% user + 0% kernel / faults: 26 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 26/ksoftirqd/3: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 29549/installer: 0% user + 0% kernel / faults: 17843 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 402/llkd: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 16/ksoftirqd/1: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 785/android.hardware.gnss@2.0-service.ranchu: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 9/ksoftirqd/0: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 21/ksoftirqd/2: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 27685/logcat: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 31/kauditd: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 379/traced_probes: 0% user + 0% kernel / faults: 2 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 29796/kworker/3:2-events_power_efficient: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 30166/kworker/u8:2-events_unbound: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 175/servicemanager: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 205/jbd2/dm-5-8: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 396/libgoldfish-rild: 0% user + 0% kernel / faults: 28 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 176/hwservicemanager: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 286/statsd: 0% user + 0% kernel / faults: 26 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 288/zygote64: 0% user + 0% kernel / faults: 342 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 388/iorapd: 0% user + 0% kernel / faults: 62 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 29253/kworker/1:3-events: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 1/init: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 11/migration/0: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 15/migration/1: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 25/migration/3: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 178/qemu-props: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 209/android.system.suspend@1.0-service: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 287/netd: 0% user + 0% kernel / faults: 2 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 321/media.log: 0% user + 0% kernel / faults: 5 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 380/traced: 0% user + 0% kernel / faults: 20 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 387/installd: 0% user + 0% kernel / faults: 5 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 401/android.hardware.biometrics.fingerprint@2.1-service: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 676/wpa_supplicant: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 1268/com.android.inputmethod.latin: 0% user + 0% kernel / faults: 3 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 2173/com.android.keychain: 0% user + 0% kernel / faults: 34 minor
07-23 08:06:46.240 E/ActivityManager(  535):   0% 29672/kworker/2:0-mm_percpu_wq: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 30072/kworker/u8:0-events_unbound: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   0% 30197/kworker/0:2-events: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):  +0% 30354/kworker/0:1-events: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):  +0% 30364/kworker/u8:1-events_unbound: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):  +0% 30445/kworker/2:1-mm_percpu_wq: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):  +0% 30448/install_server-08bc8eac: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535):  +0% 30467/com.seven.anr: 0% user + 0% kernel
07-23 08:06:46.240 E/ActivityManager(  535): 1.8% TOTAL: 0% user + 1.8% kernel + 0% iowait + 0% softirq
07-23 08:06:46.240 E/ActivityManager(  535): CPU usage from 8ms to 254ms later (2025-07-23 08:06:45.254 to 2025-07-23 08:06:45.500):
07-23 08:06:46.240 E/ActivityManager(  535):   13% 535/system_server: 0% user + 13% kernel / faults: 202 minor
07-23 08:06:46.240 E/ActivityManager(  535):     13% 30503/AnrConsumer: 0% user + 13% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   4.1% 173/logd: 0% user + 4.1% kernel
07-23 08:06:46.240 E/ActivityManager(  535):     4.1% 187/logd.auditd: 0% user + 4.1% kernel
07-23 08:06:46.240 E/ActivityManager(  535):   4.2% 303/android.hardware.graphics.composer@2.3-service: 0% user + 4.2% kernel
07-23 08:06:46.240 E/ActivityManager(  535): 7.2% TOTAL: 0% user + 7.2% kernel

四.ANR的规避

我们知道anr主要是主线程中的耗时操作导致的,所以我们应当避免在主线程做耗时操作,尽量将耗时操作放到主线程中执行:

1.代码层面规避

1.将所有耗时操作如访问网络、socket 通信、查询大量 SQL 语句、复杂逻辑计算等都放在子线程中,然后通过 handler.sendMessage、runOnUIThread 等方式更新 UI。无论如何都要确保用户界面的流畅度,如果耗时操作需要让用户等待,可以在界面上显示进度条;
2.将 IO 操作放在异步线程。在一些同步的操作主线程有可能被锁,需要等待其他线程释放响应锁才能继续执行,这样会有一定的 ANR 风险,对于这种情况有时也可以用异步线程来执行相应的逻辑,另外,要避免死锁的发生,使用 Thread 或 HandlerThread 时,调用 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置优先级,否则仍然会降低程序响应,因为默认 Thread 优先级和主线程相同,使用 Handler 处理工作线程结果,而不是使用 Thread.wait() 或 Thread.sleep() 来阻塞主线程;
3.Activity 的 onCreate() 和 onResume() 回调中避免耗时代码,BroadcastReceiver 中 onReceive() 代码也要尽量减少耗时,建议使用 IntentService 处理,各个组件的生命周期函数都不应该有太耗时的操作,即使对于后台 Service 或 ContentProvider 来讲,虽然应用在后台运行时生命周期函数不会有用户输入引起无响应的 ANR,但其执行时间过长也会引起 Service 或 ContentProvider 的 ANR。


2.增加检测机制

参考Android系统的WatchDog 的源码和原理自定义一个监控 ANR 的 WatchDog,事件 ANR 是 5s 无响应,那就设定每 5s 从 Looper 插一条消息,如果 5s 后还没执行完成就说明出现了 ANR

package com.seven.anr
import android.os.Handler
import android.os.Looper
import android.os.SystemClock
import android.util.Log




class ANRWatchDog private constructor(): Thread() {


    private val mMainHandler: Handler = Handler(Looper.getMainLooper())
    private val mAnrChecker: ANRChecker = ANRChecker()
    private var mAnrListener: ANRListener? = null
    private val lock=Object()
    override fun run() {
        // 设置为后台线程
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND)
        while (true) {

            synchronized(lock) {

                // 开始计时,往主线程 Looper 插一条消息
                mAnrChecker.schedule()
                // 每 5s 循环一次
                var waitTime = TIMEOUT.toLong()
                val start = SystemClock.uptimeMillis()
                while (waitTime > 0) { // 避免提前唤醒,保证 5s 检测一次
                    try {
                        lock.wait(waitTime)

                    } catch (e: InterruptedException) {
                        Log.w(TAG, e.toString())
                    }
                    waitTime =
                    TIMEOUT - (SystemClock.uptimeMillis() - start)

                }
            }
            // 如果前面已经等待了超过了5秒,但是这里complete是true,进入下一次循环检测
            if (!mAnrChecker.isBlocked) {
                println("$TAG complete next start ${mAnrChecker.completed}")
                continue
            }
            // 响应超过 5s ,complete未设置成true 认为已经发生了 ANR,将堆栈信息打印出来
            val stackTrace = getStackTraceInfo()
            if (mAnrListener != null) {
                println("$TAG onAnrHappened")
                mAnrListener!!.onAnrHappened(stackTrace)
            }
            mAnrListener = null
            break
        }
    }

    private fun getStackTraceInfo(): String {
        val sb = StringBuilder()
        for (element in Looper.getMainLooper().thread.stackTrace) {
            sb.append(element.toString()).append("\r\n")
        }
        return sb.toString()
    }

    private inner class ANRChecker : Runnable {
        var  completed = false
        private var startTime: Long = 0
        private var executeTime = SystemClock.uptimeMillis()
        override fun run() {
            synchronized(lock) {
                completed = true // 执行完修改标志位
                executeTime = SystemClock.uptimeMillis()//执行时间
                println("$TAG REC MSG--->> ")
            }
        }

        fun schedule() {
            println("$TAG REC START--->> ")
            completed = false
            startTime = SystemClock.uptimeMillis()
            mMainHandler.postAtFrontOfQueue(this) // 往主线程 Looper 插入一条消息
        }

        val isBlocked: Boolean
        // 如果标志位是 false 或响应时间超过 5s  返回true 表示未超过时间或者未完成 返回false表示
        get() = !completed || executeTime - startTime >= TIMEOUT
    }

    fun setANRListener(listener: ANRListener?): ANRWatchDog {
        println("$TAG setListener")
        mAnrListener = listener
        return this
    }

    interface ANRListener {
        fun onAnrHappened(stackTrack: String?)
    }

    companion object {
        private const val TAG = "ANRWatchDog"
        private const val TIMEOUT = 5000
        private var sWatchDog: ANRWatchDog? = null
        val instance: ANRWatchDog?
            get() {
                if (sWatchDog == null) {
                    sWatchDog = ANRWatchDog()
                }
                return sWatchDog
            }
    }
}


        ANRWatchDog.instance?.setANRListener(object :ANRWatchDog.ANRListener{
            override fun onAnrHappened(stackTrack: String?) {
                println("anr info:$stackTrack")
            }
        })?.start()

五.总结

anr的触发就是就是主线程的埋点因为各种各样的耗时操作,导致在规定的时间内埋点未被移除,从而导致无效应,我们应该尽量的将一些耗时操作放到子线程,避免产生anr,同时,当产生anr时,我们也可以通过日志和traces.txt来结合代码定位具体问题。