응답하지 않는 대화목록 찾기
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
이 문서에서는 ANR 스택 덤프에서 응답하지 않는 스레드를 식별하는 방법을 보여줍니다. 응답하지 않는 스레드는 다음 표와 같이 ANR 유형에 따라 다릅니다.
ANR 유형 |
응답하지 않는 스레드 |
입력 전달 |
기본 스레드 |
입력 전달에 포커스가 맞춰진 창 없음 |
기본 스레드. 이러한 유형의 ANR은 일반적으로 차단된 스레드로 인해 발생하지 않습니다. |
broadcast receiver(동기) |
onReceive() 를 실행 중인 스레드.
기본 스레드가 아닌 스레드의 맞춤 핸들러가 Context.registerReceiver 를 사용하여 지정되지 않는 한 기본 스레드입니다. |
broadcast receiver(비동기) |
코드를 살펴보고 goAsync 가 호출된 후 브로드캐스트를 처리하는 작업을 담당하는 스레드나 스레드 풀을 확인합니다. |
서비스 제한 시간 실행 중 |
기본 스레드 |
포그라운드 서비스 시작 |
기본 스레드 |
콘텐츠 제공자가 응답하지 않음 |
둘 중 하나의 경우입니다.
- 느린 콘텐츠 제공자 쿼리로 인해 ANR이 발생한 경우 바인더 스레드
- 긴 앱 시작으로 인해 ANR이 발생한 경우 기본 스레드
|
onStartJob 또는 onStopJob 에 대한 응답 없음 |
기본 스레드 |
다른 스레드나 프로세스의 근본 원인으로 인해 스레드가 응답하지 않는 경우도 있습니다. 다음 사항을 기다리고 있기 때문에 스레드가 응답하지 않을 수 있습니다.
- 다른 스레드가 보유한 잠금
- 다른 프로세스에 대한 느린 바인더 호출
응답하지 않는 스레드의 일반적인 원인
다음은 스레드가 응답하지 않는 일반적인 원인입니다.
느린 바인더 호출
대부분의 바인더 호출은 빠르지만 롱테일은 매우 느릴 수 있습니다. 이러한 상황은 기기가 로드되거나 바인더 응답 스레드가 느린 경우(예: 잠금 경합, 여러 수신 바인더 호출 또는 하드웨어 추상화 계층(HAL) 제한 시간) 발생할 가능성이 높습니다.
이 문제는 가능한 경우 동기 바인더 호출을 백그라운드 스레드로 이동하여 해결할 수 있습니다. 호출이 기본 스레드에서 발생해야 하면 호출이 느린 이유를 찾아보세요. 이를 위한 가장 좋은 방법은 Perfetto 트레이스를 사용하는 것입니다.
스택에서 BinderProxy.transactNative
또는 Binderproxy.transact
를 찾습니다.
이는 바인더 호출이 진행 중임을 의미합니다. 이 두 줄을 따르면 호출되는 바인더 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)
...
바인더를 연속으로 여러 번 호출
짧은 시간 동안 연속해서 바인더 호출을 여러 번 실행하면 스레드가 오랫동안 차단될 수 있습니다.
차단 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)
[...]
비용이 많이 드는 프레임
다음과 같이 단일 프레임에서 너무 많은 항목을 렌더링하면 프레임 지속 시간 동안 기본 스레드가 응답하지 않을 수 있습니다.
- 불필요하게 화면 밖의 많은 항목을 렌더링합니다.
- 다수의 UI 요소를 렌더링할 때
O(n^2)
와 같은 비효율적인 알고리즘을 사용합니다.
다른 구성요소에 의해 차단됨
broadcast receiver와 같은 다른 구성요소가 5초 넘게 기본 스레드를 차단하면 입력 전달 ANR 및 심각한 버벅거림이 발생할 수 있습니다.
앱 구성요소의 기본 스레드에서 과도한 작업을 실행하지 마세요. 가능하면 다른 스레드에서 broadcast receiver를 실행합니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-27(UTC)"],[],[],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."]]