Los errores de aplicación no responde (ANR) se activan cuando el subproceso de IU de la
aplicación no responde durante más de 5 segundos. Puedes leer
más sobre los errores ANR y cómo diagnosticarlos en la
documentación de Android.
Además, Crashlytics permite identificar subprocesos problemáticos específicos. Debemos
analizar los ANR y, luego, en el panel de Crashlytics,
etiquetamos los subprocesos aplicables para proporcionar sugerencias sobre cómo depurar el error ANR.
En las siguientes secciones de esta página, se explica el significado de cada etiqueta de ANR, se muestra un
ejemplo de un ANR con esa etiqueta y se proporciona una solución recomendada para depurarlo.
Triggered ANR
Un subproceso que se bloqueó durante mucho tiempo y activó el error ANR, que se anota con
esta etiqueta Triggered ANR
.
El subproceso problemático puede ser el principal de la app o cualquiera
que no responda. Sin embargo, el subproceso etiquetado como
Triggered ANR
puede o no ser la causa real del
ANR. Para proporcionar estadísticas para depurar y corregir estos errores de ANR,
Crashlytics también etiqueta cualquier otro subproceso que forme parte del ANR. En las
siguientes secciones de esta página, obtendrás información sobre las demás etiquetas que se pueden
aplicar a un subproceso.
Deadlocked
Los subprocesos identificados como involucrados en el interbloqueo que generó el error ANR se
anotarán con esta etiqueta Deadlocked
.
Se produce un interbloqueo cuando un subproceso entra en estado de espera porque otro
subproceso retiene un recurso requerido que, a su vez, está a la espera de un recurso que retiene
el primer subproceso. Si el subproceso principal de la app se encuentra en esta situación, es probable que se produzca un
error ANR.
Ver ejemplo
Aquí se muestran dos subprocesos involucrados en un interbloqueo:
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)
Recomendación
Observa los subprocesos involucrados en el interbloqueo y verifica los recursos o bloqueos
que adquirieron. Consulta
Interbloqueo y
Algoritmos de prevención de interbloqueos
para obtener posibles soluciones.
IO Root blocking
Los subprocesos que ejecutaban operaciones de E/S lentas y bloquearon el subproceso
Triggered ANR
se anotan con la etiqueta
IO Root blocking
. Si el subproceso
Triggered ANR
no está bloqueado por otros, entonces el subproceso IO Root blocking
también es uno de tipo Root blocking
.
Ver ejemplos
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 )
Recomendación
En general, tu app no debe ejecutar operaciones de E/S costosas en el subproceso
principal. Si el proceso principal es
IO Root blocking
, también puedes usar el
modo estricto
para identificar operaciones de E/S no intencionales que se ejecutan en el subproceso
principal.
Root blocking
Los subprocesos que bloquearon el subproceso etiquetado como
Triggered ANR
se anotan con la etiqueta
Root blocking
. Si un subproceso está etiquetado como
Root blocking
y
Triggered ANR
, significa que no lo están bloqueando
otros subprocesos.
Si algún subproceso Triggered ANR
espera (quizás
de forma transitiva) otros subprocesos, entonces es de tipo
Root blocking
. Un subproceso puede ser la causa
raíz de un error ANR por varios motivos.
Ver ejemplos
Estos son algunos ejemplos basados en el estado del subproceso:
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 )
Recomendación
Minimiza los trabajos de uso intensivo de CPU en el subproceso principal. Usa subprocesos de trabajador o en segundo plano
para realizar tareas que consumen muchas recursos de CPU.
Minimiza los trabajos intensivos de E/S, como realizar cargas desde una base de datos, en el subproceso principal.
Unknown root cause
Un subproceso se etiqueta con Unknown root cause
si
fue el que activó el error ANR, pero estaba inactivo en el proceso cuando se produjo
el error Crashlytics no tiene suficiente información para determinar
la causa raíz. No hay un motivo evidente por el que se haya producido este error de ANR.
Ver ejemplo
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 )
Recomendación
Sigue los consejos generales para evitar los errores ANR. Por ejemplo, identifica las
secciones de tu código en que el subproceso principal de la app pueda estar ocupado por más de 5 segundos.