Prefácio
ANR significa Application No Response e o programa não responde. O sistema Android é projetado com um mecanismo ANR, cujo objetivo é monitorar o tempo limite dos componentes com os quais interage (Atividade, etc.) e da interação do usuário (InputEvent). Isso pode determinar se o processo do aplicativo (thread principal) está travado ou respondendo muito lentamente.
Em comparação com o Crash, os problemas de ANR têm causas complexas e são difíceis de localizar. Este artigo inclui principalmente o seguinte conteúdo
- Fluxo de trabalho de ANR
- Como monitorar o ANR?
- Como localizar a causa da ANR?
Fluxo de trabalho de ANR
Muitas vezes a ANR pode ser acionada, o que geralmente pode ser dividido nos seguintes aspectos:
O princípio básico é na verdade a ideia do WatchDog: se o evento enviado não for consumido dentro de um determinado período de tempo, o ANR será acionado.
Vamos falar sobre o processo geral aqui, conforme mostrado na figura abaixo:
- Após a ocorrência de um ANR, o sistema coletará muitos dados do processo e realizará dumps de pilha para gerar um arquivo de rastreamento ANR. Dentre eles, o primeiro processo a ser coletado deve ser o processo onde ocorre o ANR.
- O sistema enviará o sinal SIGQUIT para esses processos de aplicação, e esses processos de aplicação começarão a realizar dumps de pilha após receber o sinal.
- Após a pilha de despejo do processo de aplicação ser bem-sucedida, ela se comunica com o processo do sistema por meio do Socket e grava o arquivo Trace.
- Após a gravação do arquivo Trace, se o processo onde ocorreu o ANR for o processo em primeiro plano, a caixa de diálogo aparecerá, caso contrário, o processo será eliminado diretamente.
Como monitorar o ANR?
Depois de compreender o fluxo de trabalho da ANR, como podemos monitorar a ocorrência da ANR?
Ideias de detecção de ANR WatchDog
Como a causa do ANR é que a entrada não responde dentro de um determinado período de tempo, naturalmente pensamos em enviar uma tarefa para o thread principal.Se não for executada dentro de um período de tempo, considera-se que ocorreu um ANR .
Esta ideia tem principalmente os seguintes problemas:
- Condições de tempo limite imprecisas não causam necessariamente ANR, por exemplo, um tempo limite de 5 segundos é apenas uma das condições para que um ANR ocorra quando o TouchEvent não é consumido e as outras condições não são necessariamente 5 segundos.
- Detecção ausente: Se o tempo limite for definido para 5 segundos, há uma certa probabilidade de falta de detecção (o ciclo não está sincronizado) ao detectar o ANR do TouchEvent.
Ideias para monitoramento de sinal ANR
Ao apresentar o processo geral de ANR acima, notamos que o sinal SIGQUIT será enviado quando ocorrer um ANR. Portanto, não podemos implementar o monitoramento de ANR ouvindo esse sinal? Na verdade, tanto o XCrash quanto o Matrix implementam o monitoramento ANR dessa forma.
Deve-se observar aqui que, por padrão, o processo executa dumps de pilha e gera arquivos de rastreamento ANR SignalCatcher
ouvindo sinais. SIGQUIT
Portanto, após monitorarmos SIGQUIT
o sinal, precisamos SignalCatcher
enviá-lo novamenteSIGQUIT
Se não houver nenhuma etapa para reenviar o sinal SIGQUIT para o SignalCatcher, o Android System Management Service (AMS) aguardará o processo ANR para gravar as informações da pilha. Até que o tempo limite de 20 segundos seja excedido, o AMS será forçado a interromper e continuar o processo subsequente. Isso fará com que a janela pop-up ANR seja exibida muito lentamente (porque o tempo limite é de 20 segundos) e o arquivo de rastreamento ANR completo não poderá ser gerado no diretório /data/anr.
Lidando com falsos positivos
Quando o sinal SIGQUIT é monitorado, o ANR não ocorre necessariamente.
A documentação da Matrix menciona dois casos de falsos positivos:
- Por exemplo, pode ser que outro processo tenha um ANR e o processo onde ocorreu o ANR não seja o único processo que precisa de um dump de pilha. O sistema coleta dumps de pilha de muitos outros processos e os utiliza para gerar arquivos de rastreamento ANR.
- O sinal é enviado pelo próprio fabricante ou desenvolvedor
SIGQUIT
. Enviar o sinal SIGQUIT é realmente muito fácil.
Portanto, precisamos realizar outra verificação ao ouvir o sinal: antes da janela pop-up ANR, o processo onde ocorreu o ANR será marcado com uma flag NOT_RESPONDING, e podemos obter esta flag através do ActivityManager.
private static boolean checkErrorState() {
try {
Application application = sApplication == null ? Matrix.with().getApplication() : sApplication;
ActivityManager am = (ActivityManager) application.getSystemService(Context.ACTIVITY_SERVICE);