출처: http://sunphiz.me/wp/archives/447

ANR(Application Not Responding)

ANR이란 무엇인가?

Application Not Responding의 약자이다. 단어 그대로, 어플리케이션이 응답하지 않는 경우 안드로이드 시스템에서 보여주는 에러이다. 메인 스레드(일명, UI 스레드)가 일정시간 동안 잡혀 있으면 발생한다.

언제 ANR이 발생하는가?

안드로이드 운영체제는 홈페이지 정리가 매우 잘 되어 있다. ANR의 경우는 여기에 정리되어 있는데,

  • 터치를 통한 사용자 입력이 5초 내에 처리되지 않았을 때
  • 브로드캐스트가 10초 내에 처리되지 않았을 때

가 나와있다. 하지만 여기에 나오지 않은 경우가 하나 더 있다.

  • 서비스가 20초 내로 처리되지 않을 때

안드로이드는 UI가 없는 컴포넌트인 브로드캐스트 리시버와 서비스도 메인 스레드에서 돌아가기 때문에 당연히 서비스에서도 시간 소모성 작업을 하는 경우 ANR이 발생할 수 있다.

왜 ANR이 발생하는가?

위의 ANR이 발생하는 조건을 보면 알겠지만, 앱이 무한 루프에 빠지거나 OOM(Out Of Memory)가 나야 ANR이 발생하는 것이 아니다. 시간이 좀 걸리는 처리를 해도 ANR이 충분히 발생할 수 있다. 그래서, 나처럼 자바프로그래밍에서 안드로이드로 온 사람에게는 한참동안 이해가 안될 수도 있다.

ANR이 필요한가?

그럼 이해가 안되는 것이 굳이 있어야하는 이유가 무엇인가? 내 생각에 이 부분을 이해하기 위해서는 사용자가 어떤 경우 문제가 있다고 느끼는가에 대한 것을 먼저 생각해야한다. 지금 대부분의 어플리케이션에서 사용하고 있는 프로그레스바를 생각하면 쉽다. 사용자에게 ‘움직이고 있다.’라는 사인을 주면 사용자는 기다린다. 하지만, 일명 먹통이 되면 사용자는 문제가 있다고 판단하여 전원을 끈다던가 다른 자신이 할 수 있는 해결책을 시도하는 것이다. 모바일 OS는 화면이 작아, 대부분(테블릿은 화면이 크고, 안드로이드에서 지원하는 프레그먼트는 한 화면에 여러개의 액티비티를 동작하게 할 수도 있다.)은 전체 화면을 차지한다. 이 때 화면이 정지한다면 정상적으로 동작하고 있음에도 문제가 있다고 느낄 수 있는 것이다.

그럼 어떻게 ANR을 관리해야 할까?

안드로이드 개발자 사이트를 참조해야할 질문이다. 여기에 잘 정리되어 있다. 간단히 요약하면,

  • 시간이 오래걸리는 작업은 스레드를 통해 처리하도록 권장한다.
  • 사용자에게는 프로그레스바 등을 이용해 진행 과정을 안내해 기다리도록 한다.
  • 이를 위해, 안드로이드에서 상속받아 사용할 수 있는 다양한 방법을 제공하고 있다.
  • Main thread에서 실행되는 임의의 method는 최소한의 일을 해야 합니다.
    특히 onCreate(), onResume() 과 같은 핵심 생명주기 method에서 가능한 적은 일 수행하는 것이 좋습니다.
    네트워크나 데이터베이스 operation 같은 잠재적으로 길게 실행될 가능성이 있는 작업들이나, 비트맵 크기를 조정하는 것 같은 계산상 값비싼 연산 쓰레드를 새로 생성해서 처리하는 것이 좋습니다. 물론 쓰레드에서 처리가 완료되었을 때 결과값을 받도록 handler를 설치 및 전달하는 것도 중요하지요.

    BR이 오랜 작업을 수행해야 하는 경우라면, service를 만드는 것이 좋습니다.
    BR이 activity를 띄워야 한다면, notification manager를 사용해서 사용자에게 보여주는 것으로 변경해야 합니다.

dumpstate에서 ANR의 원인을 분석하고 싶다면?

SYSTEM LOG에서 ActivityManager가 ANR 메시지를 표시하지 않는지 살펴보자. “ANR in”으로 검색하면 된다.

문제가 발생한 곳의 위치가 표시되고, 이유와 함께 CPU 사용량도 표시된다.

SYSTEM LOG에서 “SIG: 9″를 검색해 보자.  이는 시스템에서 ANR을 발생시키는 프로세스를 종료하기 위해 SIGNAL_KILL을 호출되면서 남기는 로그일 수 있다. 그 부분의 전후 로그를 살펴보자. ANR이라고 판단한 이유가 로그로 남아있을 수 있다.

EVENT LOG에서 “am_anr” 태그로 검색해 보자. anr이 발생한 어플리케이션 정보를 얻을 수 있다.

문제가 발생한 패키지 명과 PID, 이유가 표시된다.

DUMP OF SERVICE… 의 VM TRACES AT LAST ANR 부분에도 살펴보자. 문제가 없는 경우라면 다음 처럼 아무 내용이 없다.

하지만, ANR이 발생한 경우에는 어플리케이션의 콜스택이 남아있다. 글의 초반에 설명했듯이 ANR의 원인이 메인 스레드(일명 UI 스레드)이 오랫동안 바쁜 경우이므로 “main” 스레드 정보를 먼저 확인해야 한다. 특히, TIMED_WAIT나 MONITOR 에 있는지 확인하자.

그 밖에

ANR이 Activity Manager나 Window Manager 같은 곳에서 발생한 경우는 “어플리케이션이 응답이 없습니다. 기다리시겠습니까?”와 같은 메시지가 표시되지 않을 수 있다.

참조


'Programing > Android' 카테고리의 다른 글

Messenger  (0) 2016.05.06
BroadcastReceiver  (0) 2016.05.06
Process and Thread  (0) 2016.05.04
Processes and Application Life Cycle  (0) 2016.05.04
Google I/O - Memory Management For Android  (0) 2016.05.03

+ Recent posts