应用侧
-
主线程耗时
- Java Call:主线程执行耗时操作,例如复杂的计算、数据库查询、文件 I/O 等,导致 UI 线程卡顿,触发 ANR。
- Native Call:调用 JNI 代码时,C/C++ 代码执行时间过长,也会导致主线程卡死,例如长时间的 I/O 或复杂的算法计算。
-
线程状态问题
- Waiting:线程处于等待状态,等待某个锁或者
wait()方法未被notify()及时唤醒。 - Sleeping:线程主动
Thread.sleep()休眠过长,导致 UI 线程无法及时响应用户操作。 - DeadLock(死锁) :多个线程互相等待锁释放,形成循环依赖,导致线程无法继续执行。
- Blocked:线程因锁争用被阻塞,比如多个线程访问同一个资源时,锁未及时释放。
- Waiting:线程处于等待状态,等待某个锁或者
-
Binder
- Block(阻塞) :Binder 调用(跨进程通信)如果被卡住,可能是远程进程响应慢或卡死,导致调用方(通常是主线程)被阻塞,进而触发 ANR。
- 线程池耗尽:Binder 线程池有限,若大量 Binder 请求阻塞,线程池耗尽,导致新请求无法及时处理,引发 ANR。
-
内存
-
OOM(内存溢出) :1.由于 OOM 导致应用崩溃前,系统可能会尝试回收内存,这会导致 GC 频繁执行,影响主线程执行。 2.在低内存设备上,系统可能会冻结进程或降低 UI 渲染优先级,导致界面卡死,进而导致 ANR。3.OOM 本身不会直接触发 ANR,但如果 OOM 发生时,主线程正在等待某个资源(例如等待 Bitmap 加载),会导致 ANR。
-
内存泄漏:对象未被正确释放,导致长期占用大量内存,影响 GC 性能,最终影响 UI 响应速度。
-
GC:大量对象创建与销毁导致频繁 GC,导致主线程等待 GC 结束,从而影响 UI 响应速度。
-
系统侧
-
Memory(内存)
- 内存紧张:系统整体可用内存不足,导致后台进程被杀或 GC 频繁执行,影响前台应用流畅度,引发 ANR。
-
IO(输入/输出)
- 过度的磁盘读写(如频繁访问数据库、大文件读写)可能导致 IO 线程阻塞,进而影响 UI 线程的响应速度,引发 ANR。
-
CPU
- CPU 负载过高(如后台进程占用大量 CPU 资源),导致主线程的任务无法被及时调度,出现 UI 卡顿甚至 ANR。
总结
- 主线程耗时 是最常见的 ANR 原因,避免在主线程执行耗时操作。
- 线程状态问题 需要特别关注死锁、长时间等待等情况。
- Binder 调用涉及跨进程通信,避免无响应的远程服务影响 UI 线程。
- 内存管理 方面要避免 OOM 、内存泄露和频繁 GC,减少不必要的对象分配。
- 系统资源(CPU、IO、Memory) 受限时,会影响应用的运行效率,甚至导致 ANR。