查找无响应的会话
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
本文档介绍了如何识别 ANR 堆栈转储中的无响应线程。无响应的线程因 ANR 类型而异,如下表所示。
ANR 类型 |
无响应的线程 |
输入调度 |
主线程 |
输入调度未聚焦于窗口 |
主线程。此类 ANR 通常不是由阻塞的线程导致的。 |
广播接收器(同步) |
正在运行 onReceive() 的线程。除非使用 Context.registerReceiver 指定了非主线程上的自定义处理程序,否则为主线程。 |
广播接收器(异步) |
检查代码,看看在调用 goAsync 后,哪个线程或线程池负责处理广播。 |
执行服务超时 |
主线程 |
前台服务启动 |
主线程 |
content provider 没有响应 |
是以下任一情况:
- Binder 线程(如果 ANR 是由 content provider 查询缓慢导致的)。
- 主线程(如果 ANR 是由应用启动时间过长导致的)。
|
对 onStartJob 或 onStopJob 没有响应 |
主线程 |
有时,线程会由于其他线程或进程中的根本原因而无响应。线程可能会因等待以下事件而无响应:
- 其他线程持有的锁。
- 对其他进程的 binder 调用速度缓慢。
线程无响应的常见原因
以下是导致线程无响应的常见原因。
binder 调用速度缓慢
虽然大多数 binder 调用速度都很快,但长尾 binder 调用可能会非常慢。如果设备已加载或 binder 回复线程速度缓慢(例如出现锁争用、传入的 binder 调用很多或硬件抽象层 [HAL]超时等情况),更可能会发生这种情况。
您可以通过尽可能将同步 binder 调用移至后台线程中来解决此问题。如果调用必须在主线程中进行,请找出调用速度缓慢的原因。最好的方法是查看 Perfetto 跟踪记录。
在堆栈中查找 BinderProxy.transactNative
或 Binderproxy.transact
。这意味着 binder 调用正在执行中。跟随这两行代码,您可以看到调用的 binder API。在以下示例中,调用是 IAccessibilityManager.addClient
。
main tid=123
...
android.os.BinderProxy.transactNative (Native method)
android.os.BinderProxy.transact (BinderProxy.java:568)
android.view.accessibility.IAccessibilityManager$Stub$Proxy.addClient (IAccessibilityManager.java:599)
...
连续多次进行 binder 调用
在紧密循环中连续多次进行 binder 调用可能会导致线程长时间阻塞。
阻塞 I/O
切勿在主线程上执行阻塞 I/O。这是一种反模式。
锁争用
如果在获取锁定时线程处于阻塞状态,可能会导致 ANR。
以下示例展示了在尝试获取锁时主线程处于阻塞状态:
main (tid=1) Blocked
Waiting for com.example.android.apps.foo.BarCache (0x07d657b7) held by
ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD
[...]
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:5412)
[...]
阻塞线程发出了下载视频的 HTTP 请求:
ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD (tid=110) Waiting
at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:715)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1047)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:230)
at com.example.android.apps.foo.HttpRequest.execute(HttpRequest:136)
at com.example.android.apps.foo$Task$VideoLoadTask.downloadVideoToFile(RequestExecutor:711)
[...]
耗用大量资源的帧
在单个帧中渲染的内容过多可能会导致主线程该帧执行的整个过程中无响应,例如:
- 渲染许多不必要的屏幕外内容。
- 使用效率低下的算法(如
O(n^2)
)渲染许多界面元素。
被其他组件堵塞
如果另一个组件(如广播接收器)堵塞主线程超过五秒,则可能会导致输入调度 ANR 和严重卡顿。
避免在应用组件的主线程上执行任何繁重工作。尽可能在其他线程上运行广播接收器。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-27。
[null,null,["最后更新时间 (UTC):2025-07-27。"],[],[],null,["# Find the unresponsive thread\n\nThis document shows how to identify the unresponsive thread in an ANR stack\ndump. The unresponsive thread varies by type of ANR, as shown in the following\ntable.\n\n| ANR type | Unresponsive thread |\n|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Input dispatch | Main thread |\n| Input dispatch no focused window | Main thread. This type of ANR isn't usually caused by a blocked thread. |\n| Broadcast receiver (synchronous) | Thread running [onReceive()](/reference/android/content/BroadcastReceiver#onReceive(android.content.Context,%20android.content.Intent)). This is the main thread unless a custom handler on a non-main thread is specified using [Context.registerReceiver](/reference/android/content/Context#registerReceiver(android.content.BroadcastReceiver,%20android.content.IntentFilter,%20java.lang.String,%20android.os.Handler,%20int)). |\n| Broadcast receiver (asynchronous) | Check the code to see which thread or thread pool is responsible for doing the work to process the broadcast after [goAsync](https://developer.android.com/reference/android/content/BroadcastReceiver#goAsync()) is called. |\n| Executing service timeout | Main thread |\n| Foreground service start | Main thread |\n| Content provider not responding | Either: - Binder thread if ANR is caused by a slow content provider query. - Main thread if ANR is caused by a long app startup. |\n| No response to [onStartJob](/reference/android/app/job/JobService#onStartJob(android.app.job.JobParameters)) or [onStopJob](/reference/android/app/job/JobService#onStopJob(android.app.job.JobParameters)) | Main thread |\n\nSometimes the thread is unresponsive due to a root cause in a different thread\nor process. The thread can be unresponsive due to waiting on the following:\n\n- A lock held by a different thread.\n- A slow binder call to a different process.\n\nCommon causes of unresponsive threads\n-------------------------------------\n\nThe following are common causes of unresponsive threads.\n\n### Slow binder call\n\nAlthough most binder calls are quick, the long tail can be very slow. This is\nmore likely to happen if the device is loaded or the binder reply thread is\nslow, such as from lock contention, many incoming binder calls, or [hardware\nabstraction layer (HAL)](/guide/platform#hal) timeout.\n\nYou can solve this by moving synchronous binder calls to background threads\nwherever possible. If the call must happen on the main thread, find out why the\ncall is slow. The best way to do this is from Perfetto traces.\n\nLook for `BinderProxy.transactNative` or `Binderproxy.transact` in the stacks.\nThis means a binder call is taking place. Following these two lines, you can see\nthe binder API that is called. In the following example, the call is to\n`IAccessibilityManager.addClient`. \n\n main tid=123\n\n ...\n android.os.BinderProxy.transactNative (Native method)\n android.os.BinderProxy.transact (BinderProxy.java:568)\n android.view.accessibility.IAccessibilityManager$Stub$Proxy.addClient (IAccessibilityManager.java:599)\n ...\n\n### Many consecutive binder calls\n\nPerforming many consecutive binder calls in a tight loop can block a thread for\na long period.\n\n### A blocking I/O\n\nNever perform blocking I/O on the main thread. This is an antipattern.\n\n### Lock contention\n\nIf a thread is blocked when acquiring a lock, it can result in an ANR.\n\nThe following example shows the main thread is blocked when trying to acquire a\nlock: \n\n main (tid=1) Blocked\n\n Waiting for com.example.android.apps.foo.BarCache (0x07d657b7) held by\n ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD\n [...]\n at android.app.ActivityThread.handleStopActivity(ActivityThread.java:5412)\n [...]\n\nThe blocking thread is making a HTTP request to download a video: \n\n ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD (tid=110) Waiting\n\n at jdk.internal.misc.Unsafe.park(Native method:0)\n at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)\n at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:715)\n at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1047)\n at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:230)\n at com.example.android.apps.foo.HttpRequest.execute(HttpRequest:136)\n at com.example.android.apps.foo$Task$VideoLoadTask.downloadVideoToFile(RequestExecutor:711)\n [...]\n\n### Expensive frame\n\nRendering too many things in a single frame can cause the main thread to be\nunresponsive for the duration of the frame, such as the following:\n\n- Rendering many unnecessary off-screen items.\n- Using an inefficient algorithm, such as `O(n^2)`, when rendering many UI elements.\n\n### Blocked by other component\n\nIf another component, such as a broadcast receiver, blocks the main thread for\nmore than five seconds, it can cause input dispatch ANRs and serious jank.\n\nAvoid doing any heavy work on the main thread in app components. Run broadcast\nreceivers on a different thread wherever possible."]]