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 depois incluímos tags nas 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 significa cada tag de ANR, um
exemplo de ANR com a tag aplicada e uma solução recomendada para depurar o 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 ocorrido.
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.