定义:ANR(Application Not Responding)即应用无响应。
是 Android 系统检测到主线程(UI 线程)长时间阻塞时触发的机制,用户会看到 “等待 / 关闭应用” 对话框或者直接崩溃导致关闭应用。
根本原因:
主线程被耗时操作(如 IO、网络请求、复杂计算)阻塞,或因锁竞争、CPU 资源不足导致无法及时处理输入事件或系统回调。
系统检测机制,ANR 的四种(四大组件:界面、广播、服务、内容提供者)场景及超时时间:
场景 | 超时时间 | 触发条件 |
---|---|---|
输入事件超时 | 5 秒 | 用户交互(如点击、滑动)未在 5 秒内处理完成 |
前台广播超时 | 10 秒 | BroadcastReceiver.onReceive执行超过 10 秒 |
后台广播超时 | 60 秒 | 后台广播(如Context.startBroadcast)未在 60 秒内完成 |
前台服务超时 | 20 秒 | Service.onStartCommand/onBind未在 20 秒内返回 |
后台服务超时 | 200 秒 | 后台服务执行超过 200 秒 |
内容提供者超时 | 10 秒 | ContentProvider的query/insert等方法未在 10 秒内完成 |
注意:不同 Android 版本可能略有差异,需强调常见标准值。
其实大部分情况都是操作耗时导致ANR,并且最最常见的就是5秒事件超时。
除了上面的常见情况,还有另外的 锁竞争 / 死锁 也会导致ANR,场景和现场:
主线程等待子线程持有的锁(如`synchronized`块),或多个线程形成死锁循环
线程状态为`Blocked`,日志中出现`waiting for monitor entry`
这种情况比较特殊,一般可以不用考虑。
本文介绍分析ANR异常的相关日志,并且模拟相关ANR进行简单验证。
有兴趣的可以收藏看看。
下面主要以Android13的系统代码进行分析。
adb shell
# logcat | grep -i "anr"
如下可以看到ANR相关的主要日志:
IWB:/data/anr # logcat | grep -i "anr"
06-27 16:10:06.187 831 996 I WindowManager: ANR in Window{941e1d u0 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity}. Reason:941e1d com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity (server) is not responding. Waited 5001ms for MotionEvent(deviceId=7, eventTime=8503483577000, source=MOUSE, displayId=0, action=HOVER_MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=2675.3, yCursorPosition=315.4, pointers=[0: (2675.3, 315.4)]), policyFlags=0x62000001
06-27 16:10:06.753 831 7788 I ActivityManager: Dumping to /data/anr/anr_2025-06-27-16-10-06-752
06-27 16:10:12.435 831 7788 E ActivityManager: ANR in com.liwenzhi.broadcasttest (com.liwenzhi.broadcasttest/.MainActivity)
06-27 16:10:12.435 831 7788 E ActivityManager: 40% 7788/AnrConsumer: 14% user + 26% kernel
06-27 16:10:12.438 831 7788 D ActivityManager: Completed ANR of com.liwenzhi.broadcasttest in 6202ms, latency 1ms
06-27 16:10:12.478 831 7921 I DropBoxManagerService: add tag=data_app_anr isTagEnabled=true flags=0x6
上面就能看到ANR的具体位置:com.liwenzhi.broadcasttest/.MainActivity
并且说明了会生成堆栈信息文件:Dumping to /data/anr/anr_2025-06-27-16-10-06-752
这里可以看到一次ANR的日志并不会很多,除非是很多次异常会导致日志很多;
所以ANR的日志,及时抓取就好分析一点。
总结一下ANR关键字的logcat日志可以看到如下信息:
(1)"ANR in" 之后的信息是ANR的关键信息,
(2)"ANR in" 之后的 Reason:是大致说明ANR的主要原因,
(3)这里的ANR是因为:Waited 5001ms for MotionEvent,就是主线程5秒内无法响操作导致,
(4)ActivityManager: Dumping to 是生成ANR堆栈文件的日志,
(5)ANR堆栈文件有些情况看到具体哪个类的哪代码错误,
(6)生成日志之后的logcat,有大概打印当前cpu的使用情况,可以展开看看,
(7)ANR崩溃后大致会有:Force finishing、Completed ANR of 等ANR结束日志。
不同的系统版本生成的ANR堆栈文件可能会不一样,旧版本可能是: traces.txt ,主要是看logcat日志提示为准。
ANR文件比较大,直接cat看不到啥,只能adb pull到本地查看;
比如是用notpad++打开上面日志中提示anr文件:/data/anr/anr_2025-06-27-16-10-06-752
找到第一个主线程堆栈任务,搜索关键字:“main” prio=
"main" prio=5 tid=1 Sleeping //(1)当时阻塞的时候是Sleep状态
| group="main" sCount=1 ucsCount=0 flags=1 obj=0x7155d078 self=0xb400006f68651380
| sysTid=7193 nice=-10 cgrp=top-app sched=0/0 handle=0x70a8ce54f8
| state=S schedstat=( 2127060668 395250185 1857 ) utm=184 stm=27 core=4 HZ=100 // (2)state=S S表示休眠
| stack=0x7ff7985000-0x7ff7987000 stackSize=8188KB
| held mutexes=
at java.lang.Thread.sleep(Native method)
- sleeping on <0x0bd2290d> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:450)
- locked <0x0bd2290d> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:355)
at com.liwenzhi.broadcasttest.MainActivity$1.onReceive(MainActivity.java:96) //(3)报错的具体代码类和行数
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$android-app-LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1790)
at android.app.LoadedApk$ReceiverDispatcher$Args$$ExternalSyntheticLambda0.run(unavailable:2)
at android.os.Handler.handleCallback(Handler.java:942)
...
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:943)
从上面日志可以看到,报错的具体类和代码行数,进行适配修改就可以了。
上面的demo代码当时是Sleep6秒,所以是显示上面的报错。
这种是比较简单的情况,如果比较复杂的apk并且进行加密的情况,有可能看不到具体的类名称;
但是根据第一个主线程的报错堆栈,还是可以看到那个包名的应用报错的,能大致定位。
ANR堆栈文件内容比较多,很多人可能拿到了也看不出啥,主要思路:
(1)最最关键信息就是看第一个主线程的堆栈信息,搜索"main" prio= 就可以看到
(2)"main" prio=5 tid=1 Sleeping ,可以看到线程当时状态是Sleep模式,也可能是其他的状态
(3)state=S schedstat ,确认模式,S 表示Sleep
(4)再往下就是堆栈信息了,堆栈信息前面集合和后面几个都是没啥用的,一般看中间的具体的某个应用的类
整个ANR堆栈文件的大部分日志没有太多作用,重点看第一个主线程的信息即可。
网上很多的说在ANR的堆栈文件查看,cpu使用情况,关键字"CPU usage" ,或者ANR的原因,关键字"Reason:",
这些信息在Android13或者更新版本的ANR文件都是没有的,大部分信息已经放到logcat中显示了。
Android 系统中,线程状态通过 state=
字段标识,常见状态包括:
状态码 | 完整名称 | 含义 |
---|---|---|
R |
Running | 线程正在 CPU 上执行,或已准备好执行(处于就绪队列)。 |
S |
Sleeping | 线程处于睡眠状态,等待某个事件(如 I/O 完成、锁释放)唤醒。 |
D |
Disk Sleep | 深度睡眠状态(不可中断),通常与磁盘 I/O 相关,无法被信号唤醒。 |
Z |
Zombie | 僵尸进程,进程已终止但资源未被完全释放。 |
T |
Stopped | 线程被暂停(如被调试器暂停或通过信号暂停)。 |
W |
Waiting | 线程正在等待其他线程执行特定操作(如等待锁)。 |
X |
Dead | 线程已终止。 |
这种情况一般是排除是否系统卡顿,CPU使用过高导致ANR。
比如应用无限循环创建线程、界面、服务等操作,系统使用率会很高,后续打开界面或者点击按钮都可能会卡顿/ANR。
关键字:CPU usage
查看CPU使用是否达到90%以上。
一个demo应用ANR示例logcat日志如下:
logcat | grep "CPU usage"
06-25 22:22:07.938 1069 19955 E ActivityManager: CPU usage from 172492ms to 0ms ago (2025-06-25 22:19:13.574 to 2025-06-25 22:22:06.066):
06-25 22:22:07.938 1069 19955 E ActivityManager: 9.1% 1069/system_server: 5.6% user + 3.5% kernel / faults: 161504 minor 4 major
06-25 22:22:07.938 1069 19955 E ActivityManager: 4.7% 1676/com.android.launcher3: 3.9% user + 0.8% kernel / faults: 10930 minor
...
//10% TOTAL 不影响
06-25 22:22:07.938 1069 19955 E ActivityManager: 10% TOTAL: 4.5% user + 4.8% kernel + 0% iowait + 1.1% irq + 0.2% softirq
06-25 22:22:07.938 1069 19955 E ActivityManager: CPU usage from 29ms to 323ms later (2025-06-25 22:22:06.095 to 2025-06-25 22:22:06.389):
06-25 22:22:07.938 1069 19955 E ActivityManager: 158% 19849/com.liwenzhi.broadcasttest: 126% user + 32% kernel / faults: 3790 minor
06-25 22:22:07.938 1069 19955 E ActivityManager: 93% 19849/i.broadcasttest: 74% user + 18% kernel
06-25 22:22:07.938 1069 19955 E ActivityManager: 23% 19854/HeapTaskDaemon: 18% user + 4.6% kernel
...
//68% TOTAL 不影响
06-25 22:22:07.938 1069 19955 E ActivityManager: 68% TOTAL: 32% user + 32% kernel + 3.5% irq
//ANR 的应用
06-25 22:22:07.940 1069 19955 D ActivityManager: Completed ANR of com.liwenzhi.broadcasttest in 1874ms, latency 1ms
这个主要监控系统CPU使用高的主要日志。
上面可以看到CPU TOTAL 的使用率不高,并不是因为系统CPU处理不过来导致ANR;
虽然能看到某个App的使用率超过100%,但是CPU一般是四核或者八核的,
所以某个核的线程使用超过100%,对系统影响不大。
这里主要是看logcat,ANR文件虽然也有些apk的使用率但是有点看不懂;
之前旧版本的系统,网上很多都是说在 traces.txt 能看到 "CPU usage"cpu使用率的相关信息,
但是Android13之后的版本上面的ANR文件看了是没有"CPU usage" 关键字信息的。
所以ANR异常分析,主要就是看logcat 和ANR文件,进行分析;
网上有的还有说用 Systrace工具或者Studio进行分析,其实都是比较麻烦的,后面会简单说明一下。
上面是分析的大致思路,下面模拟几个情况试试,并看看日志是怎么样的。
下面主要模拟Activity、Broadcast、Service主线程Sleep和不断执行任务,导致ANR的日志。
不同的系统上报错的实际代码可能有差异,这里仅供参考。
验证测试代码:
public void sendBroadcast(View view) {
LogUtil.debug("");
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
Activity添加一个按钮和onClick事件,点击后执行修改6秒。
//执行按钮后的日志:
06-28 10:39:50.691 8700 8700 I XXXAppLog: MainActivity.java (51 )::sendBroadcast -
过滤ANR关键字的日志:
行 965: 06-28 10:39:55.884 825 1043 I WindowManager: ANR in Window{1c87832 u0 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity}. Reason:1c87832 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity (server) is not responding. Waited 5004ms for MotionEvent(deviceId=9, eventTime=4948383052000, source=MOUSE, displayId=0, action=HOVER_MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=1947.4, yCursorPosition=489.9, pointers=[0: (1947.4, 489.9)]), policyFlags=0x62000001
行 1002: 06-28 10:39:56.464 825 9610 I ActivityManager: Dumping to /data/anr/anr_2025-06-28-10-39-56-463
行 1002: 06-28 10:39:56.464 825 9610 I ActivityManager: Dumping to /data/anr/anr_2025-06-28-10-39-56-463
行 1662: 06-28 10:40:01.762 825 9610 E ActivityManager: ANR in com.liwenzhi.broadcasttest (com.liwenzhi.broadcasttest/.MainActivity)
行 1750: 06-28 10:40:01.763 825 9610 E ActivityManager: 33% 9610/AnrConsumer: 12% user + 21% kernel
行 1776: 06-28 10:40:01.766 825 9610 D ActivityManager: Completed ANR of com.liwenzhi.broadcasttest in 5800ms, latency 0ms
行 1779: 06-28 10:40:01.813 825 9745 I DropBoxManagerService: add tag=data_app_anr isTagEnabled=true flags=0x6
上面这个没啥好说的,就是最经典的5秒左右无响应导致。
可以看到大概过了5秒就出现ANR日志,并且显示原因,和产生的ANR文件。
上面可以看到主要信息:
导致ANR的主要原因:
Reason:...MainActivity (server) is not responding. Waited 5004ms for MotionEvent
ANR 报错的类:
ActivityManager: ANR in com.liwenzhi.broadcasttest.MainActivity
从logcat日志冲看不出是哪行代码导致ANR阻塞的原因,只能看出ANR堆栈日志查看具体导致ANR的代码行数。
"main" prio=5 tid=1 Sleeping
| group="main" sCount=1 ucsCount=0 flags=1 obj=0x72499078 self=0xb40000709eec97b0
| sysTid=8700 nice=-10 cgrp=top-app sched=0/0 handle=0x71e0dbb4f8
| state=S schedstat=( 2089098233 284649330 1360 ) utm=174 stm=33 core=7 HZ=100
| stack=0x7ffa47d000-0x7ffa47f000 stackSize=8188KB
| held mutexes=
at java.lang.Thread.sleep(Native method)
- sleeping on <0x05467a77> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:450)
- locked <0x05467a77> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:355)
at com.liwenzhi.broadcasttest.MainActivity.sendBroadcast(MainActivity.java:53) //阻塞位置
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:7507)
...
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:943)
这里的ANR堆栈文件可以看出,当时主线程的运行状态是Sleep和主要导致阻塞的具体代码。
把Sleep代码替换成大的for循环代码,因为在正常系统for循环中每毫秒只能打印1-2次,
所以只要在主线程循环次数大于10000,就有可能阻塞超过5秒,导致ANR。
不同的系统处理器有差异,如果要必现循环卡死,写个上亿的值进行循环肯定能复现。
其实不一定要很大值的for循环,只要在循环里面每次睡1秒,6秒后也会ANR;
这里for循环只是一直参考,也可以大致区分不同系统的处理能力。
验证测试代码:
public void sendBroadcast(View view) {
LogUtil.debug("");
int index = 0;
while (index < 1000000000) {
LogUtil.debug("自定义广播接收" + index++);
}
}
执行for循环后ANR日志如下:
行 1213: 06-30 20:14:56.520 12502 12502 I XXXAppLog: MainActivity.java (53 )::sendBroadcast -
行 1214: 06-30 20:14:56.521 12502 12502 I XXXAppLog: MainActivity.java (61 )::sendBroadcast - 自定义广播接收0
console:/vendor # logcat | grep -i ANR
06-30 20:15:02.143 826 1041 I WindowManager: ANR in Window{90cb493 u0 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity}. Reason:90cb493 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity (server) is not responding. Waited 5001ms for MotionEvent(deviceId=7, eventTime=13514939611000, source=MOUSE, displayId=0, action=HOVER_MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=1910.8, yCursorPosition=530.4, pointers=[0: (1910.8, 530.4)]), policyFlags=0x62000001
06-30 20:15:02.832 826 13042 I ActivityManager: Dumping to /data/anr/anr_2025-06-30-20-15-02-831
06-30 20:15:07.127 826 13042 E ActivityManager: ANR in com.liwenzhi.broadcasttest (com.liwenzhi.broadcasttest/.MainActivity)
06-30 20:15:07.127 826 13042 E ActivityManager: 37% 13042/AnrConsumer: 17% user + 20% kernel
06-30 20:15:07.132 826 13042 D ActivityManager: Completed ANR of com.liwenzhi.broadcasttest in 4948ms, latency 1ms
06-30 20:15:07.169 826 13167 I DropBoxManagerService: add tag=data_app_anr isTagEnabled=true flags=0x6
行 93814: 06-30 20:15:07.166 12502 12502 I XXXAppLog: MainActivity.java (61 )::sendBroadcast2 - 自定义广播接收91343
...//虽然应用界面崩溃了,但是系统还会打印一段时间,几秒或者十几秒,因为系统没有一下子杀死这个应用!
这里的for循环ANR日志和Sleep日志差不多,也是只能看到ANR无响应和哪个类相关,但是无法看到具体哪行代码;
同时这里也能看到cpu的使用比普通Sleep的情况是高一些,说明不断执行任务,只会增加cpu的使用率的。
"main" prio=5 tid=1 Runnable
| group="main" sCount=0 ucsCount=0 flags=0 obj=0x716e7078 self=0xb400006fb5d1a7b0
| sysTid=12502 nice=-10 cgrp=top-app sched=0/0 handle=0x70f7cad4f8
| state=R schedstat=( 6753134401 864033863 4948 ) utm=451 stm=223 core=1 HZ=100
| stack=0x7fc4a9b000-0x7fc4a9d000 stackSize=8188KB
| held mutexes= "mutator lock"(shared held)
native: #00 pc 0000000000554874 /apex/com.android.art/lib64/libart.so
...
at android.util.Log.println_native(Native method)
at android.util.Log.i(Log.java:181)
at com.liwenzhi.broadcasttest.LogUtil.debug(LogUtil.java:78)
at com.liwenzhi.broadcasttest.MainActivity.sendBroadcast(MainActivity.java:61) //ANR日志
at android.view.View.performClick(View.java:7507)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1213)
...
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:943)
这里没有进行Sleep而是现实Run状态,说明主线程一直在高速执行任务,导致主线程无法进行其他操作,后续就会ANR。
这里也能看到ANR阻塞的关键代码位置。
MainActivity代码,在广播接收者中Sleep12秒。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LogUtil.debug("");
registerBroadcast(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
unRegisterBroadcast(this);
}
public void sendBroadcast(View view) {
LogUtil.debug("");
Intent intent = new Intent("TestBroadcast"); //发送广播
sendBroadcast(intent);
}
public void registerBroadcast(Context context) {
LogUtil.debug("");
filter.addAction("TestBroadcast"); //自定义广播
registerReceiver(mReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED);
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) { //接收广播
final String action = intent.getAction();
LogUtil.debug("onReceive: action = " + action);
switch (action) {
case "TestBroadcast":
LogUtil.debug("自定义广播接收");
try {
Thread.sleep(120000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
break;
}
}
};
下面是点击发送广播后的ANR相关日志。
06-30 20:38:41.232 10747 10747 I XXXAppLog: MainActivity.java (45 )::sendBroadcast -
06-30 20:38:47.223 835 1001 I WindowManager: ANR in Window{179e744 u0 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity}. Reason:179e744 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity (server) is not responding. Waited 5002ms for MotionEvent(deviceId=7, eventTime=982458875000, source=MOUSE, displayId=0, action=DOWN, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000001, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=2070.1, yCursorPosition=306.4, pointers=[0: (2070.1, 306.4)]), policyFlags=0x62000001
06-30 20:38:47.790 835 10866 I ActivityManager: Dumping to /data/anr/anr_2025-06-30-20-38-47-790
06-30 20:38:52.358 835 10866 E ActivityManager: ANR in com.liwenzhi.broadcasttest (com.liwenzhi.broadcasttest/.MainActivity)
06-30 20:38:52.358 835 10866 E ActivityManager: 33% 10866/AnrConsumer: 6.1% user + 27% kernel
06-30 20:38:52.366 835 10866 D ActivityManager: Completed ANR of com.liwenzhi.broadcasttest in 5084ms, latency 1ms
06-30 20:38:52.426 835 10994 I DropBoxManagerService: add tag=data_app_anr isTagEnabled=true flags=0x6
这个的报错和上面Activity ANR事件报错的日志差不多,看不出具体类的哪行代码报错;
只能看看堆栈文件的日志了。
"main" prio=5 tid=1 Sleeping
| group="main" sCount=1 ucsCount=0 flags=1 obj=0x713cb078 self=0xb400007a716a17b0
| sysTid=10747 nice=-10 cgrp=top-app sched=0/0 handle=0x7bb7f014f8
| state=S schedstat=( 1694521387 208644145 1104 ) utm=142 stm=27 core=5 HZ=100
| stack=0x7fe8c5c000-0x7fe8c5e000 stackSize=8188KB
| held mutexes=
...
at java.lang.Thread.sleep(Thread.java:355)
at com.liwenzhi.broadcasttest.MainActivity$1.onReceive(MainActivity.java:110) //阻塞日志
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$android-app-
...
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:943)
上面可以看到阻塞的原因是休眠Sleep;
日志和UI无响应的类似,只是ANR导致的具体代码行不同而已。
把上面广播接收后的Sleep操作,替换成for循环底代码:
int index = 0;
while (index < 1000000000) {
LogUtil.debug("自定义广播接收" + index++);
}
报错后的相关日志。
06-30 20:55:36.055 19434 19434 I XXXAppLog: MainActivity.java (45 )::sendBroadcast -
...
行 54714: 06-30 20:55:41.445 835 1001 I WindowManager: ANR in Window{5f3cc3b u0 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity}. Reason:5f3cc3b com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity (server) is not responding. Waited 5003ms for MotionEvent(deviceId=7, eventTime=1996690856000, source=MOUSE, displayId=0, action=HOVER_MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=1941.7, yCursorPosition=313.6, pointers=[0: (1941.7, 313.6)]), policyFlags=0x62000001
行 61010: 06-30 20:55:42.094 835 19543 I ActivityManager: Dumping to /data/anr/anr_2025-06-30-20-55-42-093
行 61010: 06-30 20:55:42.094 835 19543 I ActivityManager: Dumping to /data/anr/anr_2025-06-30-20-55-42-093
行 108885: 06-30 20:55:46.355 835 19543 E ActivityManager: ANR in com.liwenzhi.broadcasttest (com.liwenzhi.broadcasttest/.MainActivity)
行 109033: 06-30 20:55:46.355 835 19543 E ActivityManager: 32% 19543/AnrConsumer: 8.1% user + 24% kernel
行 109077: 06-30 20:55:46.358 835 19543 D ActivityManager: Completed ANR of com.liwenzhi.broadcasttest in 4877ms, latency 1ms
行 109278: 06-30 20:55:46.396 835 19662 I DropBoxManagerService: add tag=data_app_anr isTagEnabled=true flags=0x6
这里的for循环ANR日志和Sleep日志差不多,也是只能看到ANR无响应和哪个类相关,但是无法看到具体哪行代码;
"main" prio=5 tid=1 Runnable
| group="main" sCount=0 ucsCount=0 flags=0 obj=0x713cb078 self=0xb400007a716a17b0
| sysTid=19434 nice=-10 cgrp=top-app sched=0/0 handle=0x7bb7f014f8
| state=R schedstat=( 6769272060 982465976 5922 ) utm=464 stm=212 core=0 HZ=100
| stack=0x7fe8c5c000-0x7fe8c5e000 stackSize=8188KB
| held mutexes= "mutator lock"(shared held)
native: #00 pc 0000000000554874 /apex/com.android.art/lib64/libart.so
...
at com.liwenzhi.broadcasttest.LogUtil.debug(LogUtil.java:73)
at com.liwenzhi.broadcasttest.MainActivity$1.onReceive(MainActivity.java:107) //阻塞
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$an...
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:943)
这里也能看到当时是运行状态,并且看到ANR阻塞的关键代码位置。
Activity 拉起Service,并且Service的启动过程Sleep12秒。
//MainActivity.java
public void sendBroadcast(View view) {
LogUtil.debug("");
startService(new Intent(this, MyService.class));
}
//MyService.java
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
LogUtil.debug("onCreate");
try {
Thread.sleep(12000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
LogUtil.debug("onCreate End");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtil.debug("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
LogUtil.debug("onBind");
return null;
}
}
点击按钮后,应用ANR异常后的相关日志:
07-01 10:46:21.599 827 1045 I WindowManager: ANR in Window{3fbc2a6 u0 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity}. Reason:3fbc2a6 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity (server) is not responding. Waited 5000ms for MotionEvent(deviceId=9, eventTime=7839635036000, source=MOUSE, displayId=0, action=HOVER_MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=2369.9, yCursorPosition=257.2, pointers=[0: (2369.9, 257.2)]), policyFlags=0x62000001
07-01 10:46:22.122 827 1656 I ActivityManager: Dumping to /data/anr/anr_2025-07-01-10-46-22-121
07-01 10:46:26.684 827 1656 E ActivityManager: ANR in com.liwenzhi.broadcasttest (com.liwenzhi.broadcasttest/.MainActivity)
07-01 10:46:26.685 827 1656 E ActivityManager: 34% 1656/AnrConsumer: 15% user + 18% kernel
07-01 10:46:26.687 827 1656 D ActivityManager: Completed ANR of com.liwenzhi.broadcasttest in 5053ms, latency 1ms
07-01 10:46:26.722 827 1980 I DropBoxManagerService: add tag=data_app_anr isTagEnabled=true flags=0x6
从上面日志可以看出: Reason:…MainActivity (server) is not responding. Waited 5000ms for MotionEvent.
主要原因就是:Service做了耗时操作,Activity 的点击事件5秒没有得到回应导致。
"main" prio=5 tid=1 Sleeping
| group="main" sCount=1 ucsCount=0 flags=1 obj=0x73076078 self=0xb4000070cc059380
| sysTid=29339 nice=-10 cgrp=top-app sched=0/0 handle=0x720dd904f8
| state=S schedstat=( 1696950825 243033594 1152 ) utm=146 stm=22 core=7 HZ=100
| stack=0x7fc79bb000-0x7fc79bd000 stackSize=8188KB
| held mutexes=
at java.lang.Thread.sleep(Native method)
...
at java.lang.Thread.sleep(Thread.java:355)
at com.liwenzhi.broadcasttest.MyService.onCreate(MyService.java:19) //卡死的代码位置
at android.app.ActivityThread.handleCreateService(ActivityThread.java:4510)
...
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:943)
上面的ANR堆栈日志,可以看到Service中导致阻塞的代码位置。
把上面服务中Sleep 的代码替换成大的for循环代码就会出现ANR崩溃报错。
07-01 09:52:49.169 827 1045 I WindowManager: ANR in Window{ab1f480 u0 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity}. Reason:ab1f480 com.liwenzhi.broadcasttest/com.liwenzhi.broadcasttest.MainActivity (server) is not responding. Waited 5003ms for MotionEvent(deviceId=9, eventTime=4627203031000, source=MOUSE, displayId=0, action=HOVER_MOVE, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=2041.1, yCursorPosition=326.7, pointers=[0: (2041.1, 326.7)]), policyFlags=0x62000001
07-01 09:52:49.799 827 8488 I ActivityManager: Dumping to /data/anr/anr_2025-07-01-09-52-49-798
07-01 09:52:54.048 827 8488 E ActivityManager: ANR in com.liwenzhi.broadcasttest (com.liwenzhi.broadcasttest/.MainActivity)
07-01 09:52:54.048 827 8488 E ActivityManager: 32% 8488/AnrConsumer: 8.1% user + 24% kernel
07-01 09:52:54.051 827 8488 D ActivityManager: Completed ANR of com.liwenzhi.broadcasttest in 4848ms, latency 0ms
07-01 09:52:54.104 827 8608 I DropBoxManagerService: add tag=data_app_anr isTagEnabled=true flags=0x6
07-01 09:56:35.537 827 10357 I ActivityManager: Dumping to /data/anr/anr_2025-07-01-09-56-35-536
07-01 09:56:35.603 827 10357 E ActivityManager: ANR in com.liwenzhi.broadcasttest
07-01 09:56:35.605 827 10357 I ActivityManager: Killing 8776:com.liwenzhi.broadcasttest/u0a69 (adj 0): bg anr
07-01 09:56:35.606 827 10357 D ActivityManager: Completed ANR of com.liwenzhi.broadcasttest in 104ms, latency 1ms
07-01 09:56:35.607 827 10358 I DropBoxManagerService: add tag=data_app_anr isTagEnabled=true flags=0x6
上面也是能看到 ANR in com.liwenzhi.broadcasttest/.MainActivity;
说明ANR 无响应的界面是 MainActivity,具体的阻塞代码位置需要看堆栈日志。
"main" prio=5 tid=1 Runnable
| group="main" sCount=0 ucsCount=0 flags=0 obj=0x73076078 self=0xb4000070cc059380
| sysTid=8776 nice=0 cgrp=background sched=0/0 handle=0x720dd904f8
| state=R schedstat=( 177918821666 14911248363 122763 ) utm=10908 stm=6883 core=2 HZ=100
| stack=0x7fc79bb000-0x7fc79bd000 stackSize=8188KB
| held mutexes= "mutator lock"(shared held)
native: #00 pc 0000000000554874 /apex/com.android.art/lib64/libart.so
...
at java.lang.Throwable.getStackTrace(Throwable.java:845)
at com.liwenzhi.broadcasttest.LogUtil.debug(LogUtil.java:73)
at com.liwenzhi.broadcasttest.MyService.onCreate(MyService.java:25) //阻塞的具体代码行
at android.app.ActivityThread.handleCreateService(ActivityThread.java:4510)
...
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:943)
上面日志可以看到当前阻塞的状态的运行中,可以清楚看到阻塞的具体代码类和行数。
内容提供者provider,都是类似的日志,这里就不做演示了。
这里没复现到Service和广播类型的阻塞情况,有兴趣的可以自己试试。
示例相关日志的logcat和ANR堆栈日志文件:
https://download.csdn.net/download/wenzhi20102321/91238508
1、因为系统会不定时对应用做成能否响应长操作。
2、也可能是我的系统原因,只要触摸了就会做成响应。
3、UI操作主线程阻塞的ANR时间是最短的,无论是Service阻塞还是Provider阻塞,
都是有很大概率导致UI 5秒ANR异常。
(1)主线程(UI 线程)Sleep 5 秒不一定绝对会造成 ANR,但极大概率会触发 ANR;
(2)如果只是主线程Sleep,并未操作或者触摸或者打印执行一些操作,可能不会ANR;
(3)如果是主线程Sleep过程,进行触摸、主线程打印日志、调用方法等,并且Sleep会超过5秒,都会造成ANR异常。
服务和广播的内部ANR有兴趣的可以自己尝试模拟,比如Sleep前发送延时的Handler等手段。
分析ANR异常主要步骤:
(1)分析logcat日志的anr相关信息
(2)pull ANR日志文件到本地,查看堆栈信息,看看能否查看到哪行代码导致的ANR
(3)如果上面看不出啥,就查看logcat文件,是否是因为cpu使用过高导致ANR
ANR查看的主要信息:
(1)logcat 过滤 "anr" 查看ANR的 "ANR in",可以看到ANR的大概类和原因Reason
(2)logcat 过滤:ActivityManager: Dumping to ,确定ANR堆栈日志的目录和名称
(3)ANR堆栈文件有些情况看到具体哪个类的哪代码错误
(4)ANR文件找到第一个主线程堆栈任务,搜索关键字:"main" prio= 查看堆栈日志和具体应用相关的代码
网上很多文章都是在 traces.txt 中可以查看堆栈信息,cpu使用情况,ANR原因;
其实不实用了,因为在Android13或者更新的版本已经没有 traces.txt 文件了;
并且cpu使用情况,ANR原因等日志已经默认已经打印在logcat日志中;
生成的ANR堆栈文件的名称和位置需要查看logcat中的anr提示信息确认;
在ANR堆栈文件可以看出是哪行代码导致ANR报错。
上面只是一些简单的ANR情况分析总结,
如果是比较复杂的ANR,有可能logcat比较多,ANR的堆栈文件看不出ANR具体信息;
这种情况就要总结复现手段和出现ANR的规律、logcat详细日志,等一些列思考进行分析解决。
使用 Android Studio 的 Profiler:可以查看应用的 CPU、内存和网络活动,帮助识别性能瓶颈。
使用 Traceview 或 Systrace:这些工具可以帮助你分析应用的性能问题。
# 录制包含ANR场景的systrace
adb shell systrace -t 10 -o trace.html sched gfx view input am
运行环境的systrace一般不可用了,Android13 试了一下确实不可用了,因为:
从 Android SDK 29 (Android 10) 开始,Google 已逐步弃用独立的 systrace 脚本,转而推荐使用 Android Studio 内置的 Profiler。
若使用较新版本的 SDK,可能需要手动配置路径或使用替代工具。
Systrace 命令已经基本废弃了。
这个操作使用还比较麻烦,不建议过多依赖;
不同的系统方案和不同版本的Android Studio可能有差异;
试了一下选项比较多,主要针对可调试运行的app,复杂的情况不一定能监控到。
自定义代码 ANR 监控
下面是一段监控主线程是否阻塞主要代码:
public class ANRWatchDog extends Thread {
private static final long DEFAULT_ANR_TIMEOUT = 5000; // 5秒
private final Handler handler = new Handler(Looper.getMainLooper());
private final long timeout;
public ANRWatchDog(long timeout) {
this.timeout = timeout;
}
@Override
public void run() {
while (!isInterrupted()) {
final long startTime = SystemClock.uptimeMillis();
handler.post(() -> {
final long endTime = SystemClock.uptimeMillis();
if (endTime - startTime > timeout) {
Log.e("ANR", "Main thread is blocked for " + (endTime - startTime) + "ms");
// 上报ANR信息
}
});
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
return;
}
}
}
}
试了下,其实是不行的!
所以说辅助手段不一定可靠,主要还是分析查看logcat日志+ANR文件。
并不是所有ANR都比较容易定位,比如系统服务,系统弹框,
或者系统应用/Google应用的ANR,不一定能看出哪行代码导致ANR。
下面分享一个Android 原生 Chrome 应用ANR崩溃的问题:
这个问题一般情况不出会出现,复现手段是:
系统设置wifi代理,打开浏览器的时候,一直点击浏览器,有很低概率会卡死在代理设置弹框的界面。
Chrome ANR相关的logcat日志:
行 258741: 06-25 02:45:38.965 1033 26937 D ActivityManager: created ANR temporary file:/data/anr/temp_anr_5480422974816270127.txt
行 258741: 06-25 02:45:38.965 1033 26937 D ActivityManager: created ANR temporary file:/data/anr/temp_anr_5480422974816270127.txt
行 258741: 06-25 02:45:38.965 1033 26937 D ActivityManager: created ANR temporary file:/data/anr/temp_anr_5480422974816270127.txt
行 258742: 06-25 02:45:38.965 1033 26937 I ActivityManager: Collecting stacks for pid 26769 into temporary file temp_anr_5480422974816270127.txt
行 258744: 06-25 02:45:38.968 1033 26938 I ActivityManager: Dumping to /data/anr/anr_2025-06-25-02-45-38-967
行 258744: 06-25 02:45:38.968 1033 26938 I ActivityManager: Dumping to /data/anr/anr_2025-06-25-02-45-38-967
06-25 02:45:42.467 1033 26938 I ActivityManager: Done dumping
06-25 02:45:42.477 1033 26938 E ActivityManager: ANR in com.android.chrome // ANR in
06-25 02:45:42.477 1033 26938 E ActivityManager: PID: 26769
06-25 02:45:42.477 1033 26938 E ActivityManager: Reason: No response to onStopJob
06-25 02:45:42.477 1033 26938 E ActivityManager: ErrorId: 99eb0b25-2ef0-4413-a34c-aafc0a021afc
06-25 02:45:42.477 1033 26938 E ActivityManager: Frozen: false
行 261055: 06-25 02:45:42.477 1033 26938 E ActivityManager: ANR in com.android.chrome
行 261089: 06-25 02:45:42.477 1033 26938 E ActivityManager: 20% 26939/AnrAuxiliaryTas: 4% user + 16% kernel
行 261091: 06-25 02:45:42.477 1033 26938 E ActivityManager: 4% 26938/AnrConsumer: 0% user + 4% kernel
行 261104: 06-25 02:45:42.478 1033 26938 D ActivityManager: Completed ANR of com.android.chrome in 3513ms, latency 0ms
上面日志看不出啥,能看出Chrome ANR隐藏,能看出 onStopJob 无法做成响应异常导致ANR;只能寄托ANR堆栈文件能看出啥了。
ANR堆栈日志:
"main" prio=5 tid=1 Native
| group="main" sCount=1 ucsCount=0 flags=1 obj=0x7259c828 self=0xb4000075c1235010
| sysTid=26769 nice=-10 cgrp=default sched=0/0 handle=0x771ea270a0
| state=S schedstat=( 144172880 16691789 353 ) utm=10 stm=3 core=6 HZ=100
| stack=0x7fd3b22000-0x7fd3b24000 stackSize=8188KB
| held mutexes=
...
at android.os.BinderProxy.transact(BinderProxy.java:586)
at vw1.K(chromium-TrichromeChromeGoogle6432.aab-stable-653310333:18)
at Kt3.a(chromium-TrichromeChromeGoogle6432.aab-stable-653310333:3)
at It3.onResult(chromium-TrichromeChromeGoogle6432.aab-stable-653310333:16)
at org.chromium.base.Callback.N(chromium-TrichromeChromeGoogle6432.aab-stable-653310333:1)
at ON.run(chromium-TrichromeChromeGoogle6432.aab-stable-653310333:5)
at android.os.Handler.handleCallback(Handler.java:991)
...
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:871)
DumpLatencyMs: 10.7564
ANR堆栈日志只能看出和Chrome有关,但是里面的类都被混淆了,无法确定是哪个类,所以这种情况就比较麻烦了。
另外目前Google的Chrome 应用并未开源,所以无解?
这个问题我看了一天也没有分析出啥原因,以为是系统哪里影响到了Chrome应用。
后续是更新了Chrome 应用解决了这个问题。
估计因为系统目前已经更新了最新的补丁,但是并未更新相关应用,可能会引起一些问题。