Os erros com a mensagem "O aplicativo não está respondendo" (ANR) são acionados quando a linha de
execução de interface do aplicativo ficam sem responder por mais de cinco segundos. Saiba mais
sobre os ANRs e os diagnósticos desses tipos de erro na
documentação do Android.
Além disso, o Crashlytics pode ajudar a identificar linhas de execução específicas que estejam apresentando problemas. Analisamos
os ANRs e, em seguida, marcamos as linhas de execução aplicáveis no painel do Crashlytics para dar dicas sobre como depurar o ANR.
Veja nas próximas seções o que cada tag de ANR significa, um
exemplo aplicado e uma solução recomendada para fazer a depuração desse erro.
Triggered ANR
Uma linha de execução que foi bloqueada por muito tempo e acionou o ANR é anotada com
a tag Triggered ANR
.
A linha de execução problemática pode ser a linha principal do app ou qualquer linha de execução
que não responda. Ainda assim, a linha de execução marcada como
Triggered ANR
pode ou não ser a causa real do
ANR. Para fornecer insights sobre como depurar e corrigir esses ANRs,
o Crashlytics também marca outras linhas de execução envolvidas no ANR. Saiba mais
sobre as outras tags que podem ser aplicadas a uma linha de execução nas próximas seções
desta página.
Deadlocked
Todas as linhas de execução envolvidas em um impasse que resultou no ANR são
anotadas com a tag Deadlocked
.
Um impasse ocorre quando uma linha de execução entra em um estado de espera porque um recurso
necessário é mantido por outra, que também está aguardando um recurso mantido pela
primeira. Se a linha de execução principal do app estiver nessa situação, é provável que erros ANRs
aconteçam.
Ver exemplo
Temos duas linhas de execução envolvidas em um impasse:
main (unknown): tid=1 systid=1568
com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.getPackage(PackageManagerService.java:22701)
com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.filterOnlySystemPackages(PackageManagerService.java:22787)
...
com.android.server.SystemServer.main(SystemServer.java:368)
java.lang.reflect.Method.invoke(Native method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:517)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
ActivityManager (unknown): tid=21 systid=1902
com.android.server.pm.PackageManagerService.getPackageSetting(PackageManagerService.java:23618)
com.android.server.pm.PackageManagerService.getPackageUid(PackageManagerService.java:4542)
...
android.os.Handler.handleCallback(Handler.java:907)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loop(Looper.java:216)
android.os.HandlerThread.run(HandlerThread.java:67)
com.android.server.ServiceThread.run(ServiceThread.java:44)
Recomendação
Observe as linhas de execução envolvidas no impasse e verifique os recursos/bloqueios adquiridos
por elas. Consulte
Impasse e
Algoritmos de prevenção de impasse
para encontrar possíveis soluções.
IO Root blocking
Qualquer linha de execução que estivesse executando operações de E/S com lentidão e que tenha bloqueado a
linha de execução Triggered ANR
é anotada com a
tag IO Root blocking
. Se
Triggered ANR
não for bloqueada por outras linhas de execução,
a IO Root blocking
também vai ser uma
Root blocking
.
Ver exemplos
Thread main(THREAD_STATE_TIMED_WAITING)
sun.misc.Unsafe.park( Unsafe.java:0 )
java.util.concurrent.locks.LockSupport.parkNanos( LockSupport.java:230 )
android.database.sqlite.SQLiteConnectionPool.waitForConnection( SQLiteConnectionPool.java:756 )
...
android.app.ActivityThread.main( ActivityThread.java:8192 )
Thread main(THREAD_STATE_NATIVE_WAITING)
Syscall
art::ConditionVariable::WaitHoldingLocks(art::Thread*)
art::GoToRunnable(art::Thread*)
art::JniMethodEnd(unsigned int, art::Thread*)
libcore.io.Linux.fdatasync( Linux.java:0 )
libcore.io.ForwardingOs.fdatasync( ForwardingOs.java:105 )
...
java.io.RandomAccessFile.write( RandomAccessFile.java:559 )
...
android.app.ActivityThread.main( ActivityThread.java:8192 )
Recomendação
Em geral, o app não deve executar operações de E/S de alto custo na linha de execução
principal. Se a linha de execução principal for
IO Root blocking
, também é possível usar o
Modo restrito
para identificar operações de E/S não intencionais que acontecem na linha de execução
principal.
Root blocking
Qualquer linha de execução que bloqueou a linha de execução com a tag
Triggered ANR
é anotada com a tag
Root blocking
. Se uma linha de execução for marcada como
Root blocking
e
Triggered ANR
, então não há outras fazendo o bloqueio.
Se alguma linha de execução Triggered ANR
estiver esperando (temporariamente
ou não) outras linhas, ela vai ser
Root blocking
. Uma linha de execução pode ser uma
causa raiz do ANR por vários motivos.
Ver exemplos
Temos alguns exemplos baseados no estado da linha de execução:
Thread main(THREAD_STATE_RUNNABLE)
android.os.Parcel.createTypedArray( Parcel.java:3086 )
android.content.pm.PackageInfo.<init>( PackageInfo.java:546 )
...
android.app.ActivityThread$H.handleMessage( ActivityThread.java:2166 )
android.os.Handler.dispatchMessage( Handler.java:106 )
android.os.Looper.loop( Looper.java:246 )
android.app.ActivityThread.main( ActivityThread.java:8633 )
Thread main(THREAD_STATE_BLOCKED)
DBHelper.runOnDB( DBHelper.java:97 )
DBHelper.runDb( DBHelper.java:125 )
...
java.lang.reflect.Method.invoke( Method.java:0 )
EventBus.invokeSubscriber( EventBus.java:510 )
postToSubscription( EventBus.java:437 )
...
android.os.Handler.handleCallback( Handler.java:938 )
android.os.Handler.dispatchMessage( Handler.java:99 )
android.os.Looper.loop( Looper.java:268 )
android.app.ActivityThread.main( ActivityThread.java:7904 )
Recomendação
Minimize o trabalho intensivo da CPU na linha de execução principal. Use as linhas de execução de worker ou em segundo plano
para tarefas de uso intensivo da CPU.
Minimize o trabalho intensivo de E/S, como o carregamento de um banco de dados, na linha de execução principal.
Unknown root cause
As linhas de execução que foram acionadas pelo ANR,
mas que estavam inativas quando o erro ocorreu, são marcadas como Unknown root cause
. O Crashlytics não tem informações suficientes para determinar
a causa raiz. Não há um motivo claro para esse ANR ter acontecido.
Ver exemplo
Thread main(THREAD_STATE_NATIVE_WAITING) __epoll_pwait
android::Looper::pollInner(int)
android::Looper::pollOnce(int, int*, int*, void**)
android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)
android.os.MessageQueue.nativePollOnce( MessageQueue.java:0 )
android.os.MessageQueue.next( MessageQueue.java:335 )
android.os.Looper.loop( Looper.java:193 )
android.app.ActivityThread.main( ActivityThread.java:8019 )
Recomendação
Siga as recomendações gerais sobre como evitar erros ANRs. Por exemplo, identifique os
lugares no seu código em que a linha de execução principal do app pode ficar ocupada por mais de
cinco segundos.