Processo de análise ANR

1. Conhecimento básico de ANR

1.1. Causa da ocorrência

Resumindo em uma frase: ANR ocorrerá se você não conseguir concluir o que precisa dentro do prazo especificado.

1.2. Classificação ANR

Classificação da cena que aconteceu:

  • O evento Input não foi processado por mais de 5 segundos.
  • Tempo limite de processamento do serviço, 20s em primeiro plano, 200s em segundo plano
  • Tempo limite de processamento do BroadcastReceiver, 10s em primeiro plano, 60s em segundo plano
  • Tempo limite de execução do ContentProvider, relativamente raro

De acordo com os motivos pelos quais isso aconteceu:

  • O thread principal possui operações demoradas, como layout complexo, operações de IO, etc.
  • Bloqueado pelo par do Binder
  • Bloco de bloqueio de sincronização de linha acolchoada
  • O Binder está cheio, fazendo com que o thread principal não consiga se comunicar com o SystemServer
  • Não é possível obter recursos do sistema (CPU/RAM/IO)

Do ponto de vista do processo:

  • O problema está no processo atual:
    o thread principal em si é demorado ou a fila de mensagens do thread principal tem operações demoradas,
    o thread principal é bloqueado por outros threads filhos deste processo;
  • O problema está no processo remoto (geralmente chamada de binder ou soquete e outros métodos de comunicação)

2. Análise de log de ANR

2.1. Classificação de registros

Quando ocorre um problema de ANR, um relatório de bug geralmente será arquivado.

adb bugreprot xxx

O mais importante é que o bugreport gerado tenha o traço de anr. Se quiser retirá-lo separadamente, tudo bem.

adb pull /data/anr/traces.txt xxx

Um relatório de bug completo contém as seguintes informações, que são críticas para analisar problemas de ANR

Nome do registro

efeito

Obter comando

registro do sistema

Contém informações de ponto de tempo de ocorrência de ANR, informações de CPU antes da ocorrência de ANR e também contém um grande número de informações de saída de serviço do sistema

adb logcat –b sistema

principal.log

Contém as informações geradas pelo próprio aplicativo antes que o ANR ocorra, que pode ser usado para analisar se o aplicativo está anormal; também contém as informações de saída do GC, que podem ser usadas para analisar a velocidade de reciclagem da memória e determinar se o sistema está em um estado de pouca memória ou fragmentação de memória.

adb logcat –b principal

evento.log

Contém informações sobre o ciclo de vida do aplicativo geradas por AMS e WMS, que podem ser usadas para analisar a velocidade de criação de janelas e o status de transição de foco

evento adb logcat –b

kernel.log

Incluindo informações impressas pelo kernel, processos de eliminação do LowMemoryKiller, fragmentação de memória ou memória insuficiente e exceções do driver mmc podem ser encontradas aqui.

nenhum

Então, o que você acha desses registros? Veja o caso um abaixo

2.2. Caso 1: Problema demorado de SP leva à aplicação de ANR

Geralmente, pesquise ANR primeiro para obter as informações mais intuitivas, como segue:

06-16 16: 16: 28.590 1853 2073 E ActivityManager: ANR em com.android.camera (com.android.camera/.Camera) 
06-16 16: 16: 28.590 1853 2073 E ActivityManager: PID: 27661 
06-16 16 :16:28.590 1853 2073 E ActivityManager: Motivo: tempo limite de envio de entrada expirou (com.android.camera/com.android.camera.Camera, aguardando para enviar evento não-chave porque a janela tocada não concluiu o processamento de certos eventos de entrada que foram entregue a ele há mais de 500,0 ms. Comprimento da fila de espera: 24. Idade do cabeçalho da fila de espera: 5511,1 ms.) 
06-16 16:16:28.590 1853 2073 E ActivityManager: Carga: 16,25/29,48/38,33  
06-16 16:16: 28.590 1853 2073 E ActivityManager: uso da CPU de 0 ms a 8.058 ms depois:
06-16 16:16: 28.590 1853 2073 E ActivityManager: 58% 291/mediaserver: 51% usuário + 6,7% kernel/falhas: 2457 menor 4 maior
06-16 16: 16: 28.590 1853 2073 E ActivityManager: 27% 317 / mm-qcamera-daemon: 21% usuário + 5,8% kernel / falhas: 15965 menores 06-16 16: 16: 28.590 1853 2073 E ActivityManager: 0,4 
% 288/debuggerd: 0% usuário + 0,3% kernel/falhas: 21615 secundário 87 principal 
06-16 16:16:28.590 1853 2073 E ActivityManager: 17% 27661/com.android.camera: 10% usuário + 6,8% kernel/falhas : 2412 secundário 34 principal 
06-16 16:16:28.590 1853 2073 E ActivityManager: 16% 1853/system_server: 10% usuário + 6,4% kernel/falhas: 1754 secundário 87 principal 06-16 16:16:28.590 1853 2073 E  
06-16 16:16:28.590 1853 2073 E ActivityManager: 10% 539/sensors.qcom: 7,8% usuário + 2,6% kernel/ faltas: 16 menores
ActivityManager : 4,4% 277/surfaceflinger: 1,8% usuário + 2,6% kernel/falhas: 14 menores 
06-16 16:16:28.590 1853 2073 E ActivityManager: 4% 203/mmcqd/0: 0% usuário + 4% kernel 
2073 E ActivityManager: 2,6% 3510/com. android.phone: 1,9% usuário + 0,6% kernel/falhas: 1148 menores 8 principais 
06-16 16:16:28.590 1853 2073 E ActivityManager: 2,1% 2902/com.android.systemui: 1,6% usuário + 0,4% kernel/falhas : 1272 menor 32 maior 
06-16 16:16:28.590 1853 2073 E ActivityManager: 1,6% 3110/com.miui.whetstone: 1,6% usuário + 0% kernel/falhas: 2614 menor 22 maior 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,8% 99/kswapd0: 0% usuário + 0,8% kernel 
06-16 16:16:28.590 1853 2073 E ActivityManager: 1,4% 217/jbd2/mmcblk0p25: 0% usuário + 1,4% kernel
06-16 16:16:28.590 1853 2073 E ActivityManager: 1,4% 223/logd: 0,7% usuário + 0,7% kernel/falhas: 4 menores 06-16 16:16:28.590 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,6% 29336/kworker/u:7: 0% usuário + 0,6% kernel 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,9% 12808/kworker/0:1: 0% usuário + 0,9% kernel
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,8% 35/kworker/u:2: 0% usuário + 0,8% kernel 06-16 16:16:28.590 1853 
2073 E ActivityManager: 0% 3222/com.miui .sysbase: 0% usuário + 0% kernel/falhas: 1314 secundário 12 principal 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,8% 3446/com.android.nfc: 0,4% usuário + 0,3% kernel/falhas: 1223 menor 9 maior 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,7% 10866/kworker/u:1: 0% usuário + 0,7% kernel 06-16 16:16:28.590 
1853 2073 E ActivityManager: 0,6% 642 /mdss_fb0: 0% usuário + 0,6% kernel 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,4% 6/kworker/u:0: 0% usuário + 0,4% kernel 06-16 16:16:28.590 1853 
2073 E ActivityManager: 0,4% 22924/kworker/u:6: 0% usuário + 0,4% kernel
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,3% 4421/mpdecision: 0% usuário + 0,3% kernel 06-16 16:16:28.590 
1853 2073 E ActivityManager: 0,2% 276/servicemanager: 0,1% usuário + 0,1 % kernel 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,2% 289/rild: 0,2% usuário + 0% kernel / falhas: 20 menores 06-16 16:16:28.590 
1853 2073 E ActivityManager: 0,1% 4161/ mcd: 0% usuário + 0% kernel / falhas: 9 menores 1 principais 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,1% 3/ksoftirqd/0: 0% usuário + 0,1% kernel  
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,1% 5/kworker/0:0H: 0% usuário + 0,1% de núcleo
06-16 16:16 :28.590 1853 2073 E ActivityManager: 0,1% 7/kworker/u:0H: 0% usuário + 0,1% kernel 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0% 215/flush-179:0: 0% usuário + 0% de núcleo 
1853 2073 E ActivityManager: 0,1% 321/displayfeature: 0,1 % usuário + 0% kernel 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0,1% 368/irq/33-cpubw_hw: 0% usuário + 0,1% kernel 06-16 16:16:28.590 1853 2073 E ActivityManager: 
0,1 % 403/qmuxd: 0% usuário + 0,1% kernel/falhas: 60 menores 
06-16 16:16:28.590 1853 2073 E ActivityManager: 0% 3491/com.xiaomi.finddevice: 0% usuário + 0% kernel/falhas: 706 menor 
16/06 16:16:28.590 1853 2073 E ActivityManager: 0,1% 29330/ksoftirqd/1: 0% usuário + 0,1% kernel 
06-16 16:16:28.590 1853 2073 E ActivityManager: 96% TOTAL: 56% usuário + 29% de kernel + 6,3% de iowait + 4,1% de softirq

Ao encontrar um problema de ANR, o rastreamento à nossa frente é a primeira cena do crime? Se muitas informações forem emitidas quando ocorrer um ANR, e os recursos de CPU e E/S forem relativamente escassos naquele momento, então o ponto no tempo de essa saída de log pode ser atrasada . Pode levar de 10 a 20 segundos , então às vezes precisamos estar mais vigilantes. Vamos dar um exemplo e explicá-lo linha por linha:

06-16 16: 16: 28.590 1853 2073 E ActivityManager: ANR em com.android.camera (com.android.camera/.Camera) .

Esta linha aprende que o horário em que ocorreu o ANR é 16/06 16:16:28.590, e o processo que ocorreu é com.android.camera, especificamente em com.android.camera/.Camera, onde 1853 é o pid do servidor do sistema e 2073 é o thread do ActivityManager. O pid do ActivityManager é um thread do sistema. Na verdade, há informações correspondentes no log de eventos , procure a palavra-chave am_anr

06-16 16: 16: 20.536 1853 2073 I am_anr: [0,27661, com.android.camera, 952745541, tempo limite de envio de entrada expirou (com.android.camera/com.android.camera.Camera, aguardando para enviar não- evento chave porque a janela tocada não concluiu o processamento de determinados eventos de entrada que foram entregues a ela há mais de 500,0 ms. Comprimento da fila de espera: 24. Idade do cabeçalho da fila de espera: 5511,1 ms.)]

A partir disso, você também pode determinar o ponto no tempo, o tipo, o pid do processo, o nome do processo, etc. do ANR. Continue para a próxima linha.

06-16 16:16:28.590 1853 2073 E ActivityManager: PID: 27661

Esta linha aprende que o pid do processo ANR é 27661. Em casos especiais, se o pid for 0, significa que o processo foi eliminado pelo LowMemoryKiller ou travou antes da ocorrência do ANR. Nesse caso, a transmissão do sistema não pode ser recebida. Ou uma mensagem chave, para que ocorra ANR.

06-16 16: 16: 28.590 1853 2073 E ActivityManager: Motivo: o tempo limite do despacho de entrada expirou (com.android.camera/com.android.camera.Camera, aguardando o envio de um evento não-chave porque a janela tocada não concluiu o processamento de determinados eventos de entrada que foram entregues a ele há mais de 500,0 ms. Comprimento da fila de espera: 24. Idade do cabeçalho da fila de espera: 5511,1 ms.)

Esta linha aprende que o motivo do ANR é que o tempo limite do despacho de entrada expirou

06-16 16:16:28.590 1853 2073 E ActivityManager: Carga: 16,25 / 29,48 / 38,33

Esta linha conhece a carga da CPU . No sistema operacional Linux, você também pode obter a carga por um período de tempo inserindo o tempo de atividade.

tempo de atividade 20:09:54 até 71 dias, 10:48, 1 usuário, média de carga: 0,99, 0,78, 0,86

Então, o que significa carga? Os três números após Carga significam a carga média do sistema em 1 minuto, 5 minutos e 15 minutos, respectivamente . Quando a CPU está completamente ociosa, a carga média é 0; quando a carga de trabalho da CPU está saturada, a carga média é 1. A carga pode ser usada para determinar se a carga do sistema está muito pesada. Há uma metáfora vívida: imagine uma CPU como uma ponte. Há apenas uma faixa na ponte. Todos os veículos devem passar por essa faixa. A carga do sistema é 0, o que significa que não há um único carro na ponte. O sistema a carga é 0,5, o que significa que há carros em metade dos trechos da ponte, e a carga do sistema é 1,0, o que significa que há carros em todos os trechos da ponte, o que significa que a ponte está "cheia", e a carga do sistema é 2,0, o que significa que há muitos veículos e a ponte está cheia (100%) e há o dobro de veículos esperando para entrar na ponte. A capacidade de tráfego da ponte é a carga máxima de trabalho da CPU; os veículos na ponte são processos aguardando processamento pela CPU.

A regra é esta:
quando a carga do sistema é consistentemente superior a 0,7, você deve começar a investigar qual é o problema e evitar que a situação piore.
Quando a carga do sistema continuar maior que 1,0, você deverá encontrar uma solução para diminuir esse valor.
Quando a carga do sistema atinge 5.0, indica que seu sistema tem um problema sério.

Se a carga do sistema em apenas um minuto for superior a 1,0 e os outros dois períodos de tempo forem inferiores a 1,0, isso indica que é apenas um fenômeno temporário e que o problema não é sério.
Se a carga média do sistema for superior a 1,0 em 15 minutos (após ajustar o número de núcleos da CPU), isso indica que o problema persiste e não é um fenômeno temporário. Portanto, você deve observar principalmente a “carga do sistema de 15 minutos” como um indicador da operação normal do computador.

Nossos telefones celulares atuais têm uma arquitetura de CPU multi-core. Existem muitos oito núcleos, o que significa que o poder de processamento da CPU é multiplicado por 8. O tempo de execução de cada núcleo pode ser obtido no seguinte arquivo, /sys/devices/system / Leitura de cpu/cpu%d/cpufreq/stats/time_in_state, %d representa o núcleo da CPU. O arquivo registra o tempo de execução da CPU em cada frequência desde a inicialização até a leitura do arquivo, unidade: 10 mS.

Use adb shell cat /sys/devices/system/cpu/cpu1/cpufreq/stats/time_in_state para verificar a frequência

Use adb shell cat /sys/devices/system/cpu/cpu1/cpufreq/stats/time_in_state para visualizar o tempo de 
frequência 
652800 1813593 
1036800 46484 
1401600 521974 
1689600 2956667 
1843200 83065 1958400 5 3516 
2016000 
251693

Para obter mais detalhes sobre a carga, consulte Compreendendo a carga do sistema Linux , mas não entre em muitos detalhes.

16/06 16:16:28.590 1853 2073 E ActivityManager: uso da CPU de 0 ms a 8058 ms depois: 
16/06 16:16: 28.590 1853 2073 E ActivityManager: 58% 291/mediaserver: 51% usuário + 6,7% kernel/falhas: 2457 menor 4 maior 
06-16 16:16:28.590 1853 2073 E ActivityManager: 27% 317/mm-qcamera-daemon: 21% usuário + 5,8% kernel/falhas: 15965 menor 06-16 16:16:28.590 1853 2073 
E ActivityManager: 0,4% 288/debuggerd: 0% usuário + 0,3% kernel/falhas: 21615 menor 87 principal 
06-16 16:16:28.590 1853 2073 E ActivityManager: 17% 27661/com.android.camera: 10% usuário + 6,8 % kernel / falhas: 2412 menores 34 principais 
.... 
06-16 16:16:28.590 1853 2073 E ActivityManager: 96% TOTAL: 56% usuário + 29% kernel + 6,3% iowait + 4,1% softirq 
.....

Neste log, você pode obter o uso da CPU dos principais processos quando ocorre ANR. O usuário representa o espaço do usuário e o kernel representa o espaço do kernel. Geralmente, as regras a seguir se aplicam.

  • Se a taxa de ocupação da CPU kswapd0 for alta, o sistema geral funcionará lentamente, causando vários ANRs. Encaminhe o problema para "Otimização de Memória" e peça para otimizá-lo.
  • O alto uso da CPU logada também pode causar congelamentos do sistema e ANR, porque a operação de cada processo para gerar LOG é bloqueada e executada de forma extremamente lenta.
  • Vold ocupa muita CPU e pode causar congelamentos do sistema e ANR. Investigue primeiro se você é responsável pelo armazenamento.
  • O uso da CPU do qcom.sensor é muito alto, o que pode causar atraso. Investigue o sistema.
  • O uso da CPU do próprio aplicativo é alto e há uma grande probabilidade de problemas no aplicativo
  • O uso da CPU do sistema não é alto, mas o thread principal está aguardando um bloqueio e há uma grande probabilidade de problemas no aplicativo.
  • A aplicação está no estado D e ocorre ANR. Se a última operação for refrigerar, a aplicação é congelada, o que normalmente é causado pela otimização do consumo de energia.

Ok, do log acima obtivemos as informações básicas do ANR. Para descobrir onde está o bloqueio, precisamos contar com o arquivo de rastreamento. Geralmente no diretório anr. Pesquise a pilha do thread principal neste arquivo de rastreamento, da seguinte forma:

----- pid 27661 em 16/06/2017 16:16:20 ----- 
Linha cmd: com.android.camera 
"main" prio=5 tid=1 Esperando 
 | group="principal" sCount=1 dsCount=0 obj=0x75a4b5c8 self=0xb4cf6500 
 | sysTid=27661 nice=-10 cgrp=padrão sched=0/0 handle=0xb6f6cb34 
 | estado=S schedstat=( 11242036155 8689191757 38520 ) utm=895 stm=229 núcleo=0 HZ=100 
 | pilha=0xbe4ea000-0xbe4ec000 stackSize=8 MB 
 | mantidos mutexes= 
 em java.lang.Object.wait!(Método nativo) 
 - aguardando <0x09e6a059> (um java.lang.Object) 
 em java.lang.Thread.parkFor$(Thread.java:1220) 
 - bloqueado <0x09e6a059 > (um java.lang.Object) 
 em sun.misc.Unsafe.park(Unsafe.java:299) 
 em java.util.concurrent.locks.LockSupport.park(LockSupport.java:
 em java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:810) 
 em java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptably(AbstractQueuedSynchronizer.java:970) 
 em java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSha vermelhoInterruptamente (AbstractQueuedSynchronizer.java:1278) 
 em java.util.concurrent.CountDownLatch.await(CountDownLatch.java:203) 
 em android.app.SharedPreferencesImpl$EditorImpl$1.run(SharedPreferencesImpl.java:366) 
 em android.app.QueuedWork.waitToFinish (QueuedWork.java:88) 
 em android.app.ActivityThread.handleStopActivity(ActivityThread.java:3605) 
 em android.app.ActivityThread.access$1300(ActivityThread.java:153)
 em android.app.ActivityThread$H.handleMessage(ActivityThread.java:1399) 
 em android.os.Handler.dispatchMessage(Handler.java:102) 
 em android.os.Looper.loop(Looper.java:154) 
 em android. app.ActivityThread.main(ActivityThread.java:5528) 
 em java.lang.reflect.Method.invoke!(Método nativo) 
 em com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:740) 
 em com .android.internal.os.ZygoteInit.main(ZygoteInit.java:630)

Explique o significado de alguns campos

Campo

significado

tempo=1

Número do tópico

sysTid=27661

O número do thread e o número do processo do thread principal são iguais

Esperando

Estado do thread, onde state também é o estado do thread, se state=D significa que a camada inferior está bloqueada.

legal

Quanto menor o valor agradável, maior será a prioridade. Por ser o thread principal, nice=-10 aqui, você pode ver que a prioridade é muito alta.

schedstat

Os três números entre colchetes são os tempos de execução, execução e troca em ordem. Tempo de execução: tempo de execução da CPU, unidade ns. Tempo executável: tempo de espera da fila RQ, em ns. Tempos de troca: o número de trocas de agendamento de CPU

hum

No momento em que o thread é executado no modo de usuário, a unidade é instantânea

stm

No momento em que o thread é executado no modo kernel, a unidade é instantânea

contagem

O número de vezes que este tópico foi suspenso

dsCount

O número de vezes que um thread foi suspenso pelo depurador. Quando um processo é depurado, sCount será redefinido para 0. Após a depuração, sCount aumentará dependendo se foi suspenso normalmente, mas dsCount não será redefinido para 0, então dsCount também pode ser usado. Usado para determinar se este thread foi depurado

auto

O endereço do próprio thread

Vamos falar sobre o status do tópico

estado

valor

ilustrar

THREAD_ZOMBIE

0

TERMINADO

THREAD_RUNNING

1

RUNNABLE ou em execução agora

THREAD_TIMED_WAIT

2

TIMED_WAITING em Object.wait()

THREAD_MONITOR

3

BLOQUEADO em um monitor

THREAD_INITIALIZING

5

alocado ainda não está em execução

THREAD_STARTING

6

começou ainda não está na lista de tópicos

THREAD_NATIVE

7

off em um método nativo JNI

THREAD_VMWAIT

8

aguardando um recurso VM

THREAD_SUSPENDED

9

suspenso geralmente pelo GC ou depurador

Então, como resolver este problema?Através da introdução básica acima e do arquivo de rastreamento, sabemos que o ponto bloqueado é

em java.util.concurrent.CountDownLatch.await(CountDownLatch.java:203) 
 em android.app.SharedPreferencesImpl$EditorImpl$1.run(SharedPreferencesImpl.java:366) 
 em android.app.QueuedWork.waitToFinish(QueuedWork.java:88) 
 em android.app.ActivityThread.handleStopActivity(ActivityThread.java:3605) 
 em android.app.ActivityThread.access$1300(ActivityThread.java:153)

Vejamos primeiro QueuedWork.waitToFinish

77 /** 
78 * Termina ou aguarda a conclusão das operações assíncronas. 
79 * (por exemplo, SharedPreferences$Editor#startCommit escreve) 
80 * 
81 * É chamado a partir do onPause() da classe base da Activity, após 
82 * OnReceive do BroadcastReceiver, após o tratamento do comando Service, 
83 * etc. (para que o trabalho assíncrono nunca seja perdido) 
84 */ 
85 public static void waitToFinish() { 
86 Executável toFinish; 
     //等待所有等待完成的任务完成
87 while ((toFinish = sPendingWorkFinishers.poll()) != null) { 
88 toFinish.run(); 
89} 
90}

QueuedWork.waitToFinish será chamado após onPause de Activity ou onReceive de BroadcastReceiver para garantir que a execução da tarefa assíncrona seja concluída. Em waitToFinish, itere todas as tarefas aguardando para serem concluídas em sPendingWorkFinishers e aguarde sua conclusão. Vejamos SharedPreferencesImpl.apply.Este método colocará tarefas aguardando para serem gravadas no sistema de arquivos na fila de conclusão de espera do QueuedWork.

361 public void apply() { 
362 final MemoryCommitResult mcr = commitToMemory(); 
363 final Runnable awaitCommit = new Runnable() { 
364 public void run() { 
365 try { 
366 mcr.writeedToDiskLatch.await(); 
367 } catch (InterruptedException ignorado) { 
368 } 
369 } 
370 }; 
371 
     //Coloque tarefas aguardando para serem gravadas no sistema de arquivos na fila de espera do QueuedWork 
372 QueuedWork.add(awaitCommit); 
373 ... ... ... ... ... ... 
388 }

Embora o próprio método apply possa retornar rapidamente, quando o onPause da Activity for chamado, ele aguardará a conclusão da tarefa de gravação no sistema de arquivos. Em outras palavras, embora o próprio apply não bloqueie o thread de chamada, ele transferirá o tempo de espera para o thread principal. Portanto, se a tarefa de gravação for executada lentamente e a operação sp de atividade, serviço e transmissão não for concluída no final do ciclo de vida, o thread principal será bloqueado e causará ANR. Neste ponto da análise, é óbvio que se trata de um problema de sistema e o App é impotente. Felizmente, esse problema foi amenizado nos telefones Xiaomi e a solução não será divulgada. De modo geral, as regras para observar vestígios são as seguintes:

  • Quando ocorre um ANR, o processo correspondente não pode ser encontrado no rastreamento. Verifique se o Android Runtime está Desligado devido à falha do aplicativo. Se for Desligado, verifique o motivo do Desligamento neste momento.
  • Ocorre um ANR em um aplicativo. Se o thread principal estiver executando getContentProvider, ele estará solicitando o ContentProvider de outro aplicativo. Neste momento, verifique o processo host do ContentProvider de destino para ver o que ele está fazendo.
  • Se o thread principal executar operações de banco de dados ou solicitações de rede, deverá haver um problema com o próprio aplicativo.
  • Se o thread principal aguardar bloqueios mantidos por outros threads e o thread de destino executar operações de banco de dados ou solicitações de rede, então há um problema com o próprio aplicativo.

Aqui começamos apenas com um caso para nos familiarizarmos com o processo básico de análise ANR. Vamos resumir a rotina acima aqui:

  • Pegue o relatório de bug, pesquise ANR e verifique a hora e o processo de ocorrência
  • Encontre o rastreamento do thread principal de acordo com o processo e encontre o local bloqueado
  • Análise e solução com base no código-fonte.Claro
    que através dessas duas etapas podemos localizar a causa do ANR, o que mostra que temos relativa sorte, mas na maioria das vezes não é assim.

Acima, analisamos um ANR causado por um problema no sistema. Aqui você pode pensar que meu aplicativo não funcionou, mas ocorreu um ANR. No futuro, posso culpar diretamente o sistema. Não, o problema específico ainda precisa ser analisado em detalhes., para duvidar do sistema, precisamos de evidências. De onde vem a evidência, ou do Log. Continue para a terceira seção, o plano de análise demorado do sistema.

3. Plano de análise demorado do sistema

O sistema realizou algumas operações de análise demoradas. Em alguns fabricantes de telefones celulares, existem outras melhorias no Log. Aqui estão algumas das mais comuns.

3.1、fichário_amostra

  • A. Descrição da função: Monitore a situação demorada da transação do fichário do thread principal de cada processo. Quando o limite é excedido, as informações de chamada de destino correspondentes são emitidas. Ele é ativado em 1000 ms por padrão.
  • B.log格式: 52004 binder_sample (descritor|3),(method_num|1|5),(time|1|3),(blocking_package|3),(sample_percent|1|6)
  • Exemplo C.log:
2754 2754 I binder_sample: [android.app.IActivityManager,35,2900,android.process.media,5]

A partir do log acima, pode-se concluir que
1. Thread principal 2754;
2. Execute a interface android.app.IActivityManager

  1. O código do método correspondente =35 (ou seja, STOP_SERVICE_TRANSACTION),
  2. O tempo gasto é de 2900ms.
  3. O pacote onde este bloco está localizado é android.process.media, e o último parâmetro é a proporção da amostra (não tem muito valor)

3.2、dvm_lock_sample

  • A. Descrição da função: Quando o tempo bloqueado por um thread aguardando bloqueio excede o limite, o status do bloqueio atual é exibido;
  • B.log格式: 20003 dvm_lock_sample (process|3),(main|1|5),(thread|3),(time|1|3),(file|3),(line|1|5),( arquivo_proprietário|3),(linha_proprietária|1|5),(porcentagem_de_amostra|1|6)
  • Exemplo C.log:
dvm_lock_sample: [system_server,1,Binder_9,1500,ActivityManagerService.java,6403,-,1448,0]

Isso significa que system_server: Binder_9, executado na linha 6403 de ActivityManagerService.java, estava aguardando o bloqueio do AMS, e o bloqueio é mantido pela linha 1448 do mesmo arquivo, fazendo com que o encadeamento Binder_9 seja bloqueado por 1500ms.

3.3、 Fichário sem pasta

  • A. Descrição da função: Quando o conjunto de threads de processos como system_server é usado e não há threads ociosos, a comunicação do binder está em estado de fome.Se o estado de fome exceder um certo limite, as informações serão exibidas;
  • B. Parâmetros de controle de nuvem: persist.sys.binder.starvation (valor padrão 16ms)
  • Exemplo C.log:
1232 1232 "Conjunto de encadeamentos do binder (16 encadeamentos) com fome por 100 ms"
  • Análise D.log: O conjunto de threads do processo system_server fica cheio por até 100 ms.

Geralmente, depois de obter essas informações, elas podem nos ajudar a determinar se a causa do problema é o sistema ou o aplicativo. Veja o caso 2 abaixo:

3.4. Caso 2: Crazy Binder Call leva ao ANR do aplicativo

Pesquisar ANR em

08-28 18:54:00.110 1000 1825 1848 E ActivityManager: ANR em com.jeejen.family (com.jeejen.family/com.jeejen.home.launcher.ShoppingActivity) 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: PID: 20576 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: Motivo: tempo limite de despacho de entrada expirou (com.jeejen.family/com.jeejen.home.launcher.WelcomeActivity, aguardando para enviar evento não-chave porque a janela tocada não concluiu o processamento de determinados eventos de entrada que foram entregues a ela há mais de 500,0 ms. Comprimento da fila de espera: 2. Idade do cabeçalho da fila de espera: 10064,4 ms.) 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 
Pai : com.jeejen.family/com.jeejen.home.launcher.WelcomeActivity 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: Carga: 1,25 / 1,1 / 1,37
28/08 18:54:00.110 1000 1825 1848 E ActivityManager: uso da CPU de 5166ms a 0ms atrás (28/08/2018 18:53:51.270 a 28/08/2018 18:53:56.436): 28/08 18 
: 54:00.110 1000 1825 1848 E ActivityManager: 7,7% 1825/system_server: 5,6% usuário + 2,1% kernel/falhas: 1329 minor 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 3,6% 20683/com.jeeje n.família :pushcenter_pushservice: 3% usuário + 0,5% kernel / falhas: 542 menores 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 2,7% 4114/cnss_diag: 1,9% usuário + 0,7% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 2,1% 422/kworker/u16:7: 0% usuário + 2,1% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 1,9% 20830/com.jeejen.family:store: 1,3 % usuário + 0,5% kernel/falhas: 199 menores
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 1,7% 20608/com.jeejen.family:pushcenter: 1,1% usuário + 0,5% kernel 08-28 18:54:00.110 1000 
1825 1848 E ActivityManager: 1,5% 72 5 /[email protected]: 0,7% usuário + 0,7% kernel / falhas: 1 menor 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,9% 3538/com.android.systemui: 0,7% usuário + 0,1% kernel / falhas: 11 menores 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,5% 241/crtc_commit:111: 0% usuário + 0,5% kernel 08-28 18:54:00.110 1000 1825 1848 
E ActivityManager: 0,5% 419/kworker/u16:4: 0% usuário + 0,5% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,5% 786/surfaceflinger: 0,5% usuário + 0% kernel
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,3% 185/IPCRTR_dsps_sme: 0% usuário + 0,3% kernel 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,3% 730/ 
android.hard ware.wifi @ 1.0-service: 0,1% usuário + 0,1% kernel / falhas: 28 menores 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,3% 820/dsps_IPCRTR: 0% usuário + 0,3% kernel 
08-28 18:54 :00.110 1000 1825 1848 E ActivityManager: 0,3% 1147/msm_irqbalance: 0,1% usuário + 0,1% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,3% 4113/sugov:0: 0% usuário + 0. 3% de núcleo 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 10/rcuop/0: 0% usuário + 0,1% kernel 08-28 18:54:00.110 1000 
1825 1848 E ActivityManager: 0,1% 18/ksoftirqd/1 : 0% usuário + 0,1% kernel
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0% 34/ksoftirqd/3: 0% usuário + 0% kernel 08-28 18:54:00.110 1000 
1825 1848 E ActivityManager: 0% 53/rcuop/5 : 0% usuário + 0% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0% 61/rcuop/6: 0% usuário + 0% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager : 0,1% 242/crtc_event:111: 0% usuário + 0,1% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 538/ueventd: 0,1% usuário + 0% kernel 
08-28 18:54: 00.110 1000 1825 1848 E ActivityManager: 0,1% 577/jbd2/sda22-8: 0% usuário + 0,1% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 591/logd: 0,1% usuário + 0% núcleo
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 719/[email protected]: 0,1% usuário + 0% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager : 0,1% 928/motor térmico: 0% usuário + 0,1% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 3490/cds_mc_thread: 0% usuário + 0,1% kernel 
08-28 18:54: 00.110 1000 1825 1848 E ActivityManager: 0,1% 3491/cds_ol_rx_threa: 0% usuário + 0,1% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 3680/com.android.phone: 0% usuário + 0,1% kernel/falhas: 16 menores 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 4248/com.miui.daemon: 0,1% usuário + 0% kernel/falhas: 4 menores
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 4488/com.miui.powerkeeper: 0,1% usuário + 0% kernel / falhas: 10 menores 08-28 18:54:00.110 1000 1825 1848 E ActivityManager 
: 0,1% 5545/com.lbe.security.miui: 0% usuário + 0,1% kernel/falhas: 6 menores 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 6490/kworker/u17:2: 0% usuário + 0,1% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 7535/kworker/u16:15: 0% usuário + 0,1% kernel 08-28 18:54:00.110 1000 1825 1848 E ActivityManager 
: 0% 7723/kworker/3:5: 0% usuário + 0% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 15111/kworker/1:0: 0% usuário + 0,1% kernel
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 15138/kworker/3:0: 0% usuário + 0,1% kernel 08-28 18:54:00.110 1000 
1825 1848 E ActivityManager: 0% 19857/kworker /0:3: 0% usuário + 0% kernel 
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0,1% 20492/kworker/5:3: 0% usuário + 0,1% kernel 
08-28 18:54: 00.110 1000 1825 1848 E ActivityManager: 3,8% TOTAL: 2% usuário + 1,1% kernel + 0% iowait + 0,3% irq + 0,1% softirq

De acordo com a rotina acima, tudo está relativamente normal. O horário da ocorrência é provavelmente 28/08 18:54:00.110. Estou olhando o rastreamento do thread principal.

----- pid 20576 em 28/08/2018 18:53:56 ----- 
Linha cmd: com.jeejen.family 
"main" prio=5 tid=1 Nativo 
| group="main" sCount=1 dsCount=0 sinalizadores=1 obj=0x77ffca18 self=0xecfce000 
| sysTid=20576 nice=-10 cgrp=padrão sched=0/0 handle=0xf0bf2494 
| estado = S schedstat = (628294395 402363898 957) utm = 42 stm = 20 núcleo = 4 HZ = 100 
| pilha=0xff5fe000-0xff600000 stackSize=8MB 
| retidos mutexes= 
kernel: (não foi possível ler /proc/self/task/20576/stack) 
nativo: #00 pc 00053cfc /system/lib/libc.so (__ioctl+8) 
nativo: #01 pc 00021cd3 /system/lib /libc.so (ioctl+30) 
nativo: #02 pc 0003d3f5 /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+204)
nativo: #03 pc 0003dde3 /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+26) 
nativo: #04 pc 0003713d /system/lib/libbinder.so ( android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36) 
nativo: #05 pc 000c3cf1 /system/lib/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject *, int, _jobject*, _jobject*, int)+200) 
em android.os.BinderProxy.transactNative(método nativo) 
em android.os.BinderProxy.transact(Binder.java:1127) 
em android.net.wifi.IWifiManager $Stub$Proxy.getConnectionInfo(IWifiManager.java:1441) 
em android.net.wifi.WifiManager.getConnectionInfo(WifiManager.java:1778)
at org.chromium.net.NetworkChangeNotifierAutoDetect$WifiManagerDelegate.getWifiInfoLocked(NetworkChangeNotifierAutoDetect.java:28) 
at org.chromium.net.NetworkChangeNotifierAutoDetect$WifiManagerDelegate.getWifiSsid(NetworkChangeNotifierAutoDetect.java:22) 
- locked <0x0f4edae7> (a java.lang.Object ) 
em org.chromium.net.NetworkChangeNotifierAutoDetect.getCurrentNetworkState(NetworkChangeNotifierAutoDetect.java:67) 
em org.chromium.net.NetworkChangeNotifierAutoDetect.<init>(NetworkChangeNotifierAutoDetect.java:21) 
em org.chromium.net.NetworkChangeNotifier.setAutoDetectConnectivityStateInternal(NetworkChange Notificador. java:61)

Parece que a chamada do fichário está bloqueada e a interface de chamada é IWifiManager.getConnectionInfo(). Por ser uma chamada de fichário, verifique binder_sample.

08-28 18:54:01.384 10171 20576 20576 I binder_sample: [android.net.wifi.IWifiManager,24,16004,com.jeejen.family,100] 
08-28 18:54:04.868 10171 20576 20576 I binder_ amostra: [ android.net.wifi.IWifiManager,24,3479,com.jeejen.family,100] 
08-28 18:56:12.712 10171 21885 21885 I binder_sample: [android.net.wifi.IWifiManager,24,8963,com.jeejen .família,100]

Pode-se observar que às vezes próximo ao ANR, a chamada do binder usando a interface IWifiManager demora muito, então esse é um motivo do sistema? Então dê uma olhada no código de seu par Sysytem.

1763 /** 
1764 * Consulte {@link android.net.wifi.WifiManager#getConnectionInfo()} 
1765 * @return as informações de Wi-Fi, contidas em {@link WifiInfo}. 
1766 */ 
1767 @Override 
1768 public WifiInfo getConnectionInfo() { 
1769 aplicarAccessPermission(); 
1770 mLog.trace("getConnectionInfo uid=%").c(Binder.getCallingUid()).flush(); 
1771 /* 
1772 * Certifique-se de que temos as informações mais recentes, enviando 
1773 * uma solicitação de status ao suplicante. 
1774 */ 
1775 return mWifiStateMachine.syncRequestConnectionInfo(); 
1776}
1521 WifiInfo público syncRequestConnectionInfo() { 
1522 Resultado WifiInfo = new WifiInfo(mWifiInfo); 
1523 resultado de retorno; 
1524}

getConnectionInfo chama syncRequestConnectionInfo em wifiStateMachine diretamente por meio de wifiService. A implementação desta parte não será bloqueada. O Binder está cheio? Isso não é visto no rastreamento, então o que está acontecendo? Tentamos reproduzir esse problema, mas felizmente foi relativamente fácil de reproduzir.

09-04 18:24:29.182 D/WifiStateMachine( 1312): syncRequestConnectionInfo/in SSID: MIOffice-5G, BSSID: 70:3a:0e:2c:bb:f1, MAC: 80:ad:16:4c:0b: fe, estado do suplicante: CONCLUÍDO, RSSI: -44, velocidade do link: 400 Mbps, frequência: 5180 MHz, ID de rede: 0, dica medida: falso, pontuação: 60 09-04 18: 24: 29.182 D/WifiStateMachine (1312): syncRequestConnectionInfo /out SSID: MIOffice-5G, BSSID: 70:3a:0e:2c:bb:f1, MAC: 80:ad:16:4c:0b:fe, Estado do suplicante: COMPLETED, RSSI: -44, Velocidade do link: 400Mbps , Frequência: 5180 MHz, Net ID: 0, Dica medida: falso, pontuação: 60

Verificou-se que o thread principal estava gerando uma grande quantidade do log acima, e o desktop minimalista chamou essa interface 160 vezes em 1 minuto, fazendo com que o SystemServer não conseguisse responder ao aplicativo em tempo hábil, fazendo com que o próprio aplicativo ANR. Problemas como ANR causados ​​por chamadas do Binder são muito comuns e existe o risco de ser bloqueado. Neste momento, você pode tentar executá-lo de forma assíncrona. Em segundo lugar, não faça um grande número de chamadas do Binder em um curto período de tempo . Este comportamento pode causar problemas no próprio App ou, na pior das hipóteses, o sistema pode travar e reiniciar com o Watchdog. .

3.5. Caso 3: O tempo limite da transmissão causa ANR do aplicativo

Vamos continuar com o Caso 3. De acordo com a rotina acima, primeiro verifique a hora em que ocorreu o ANR no log de eventos.

12-17 06: 02: 14.463 1566 1583 Eu sou_anr: [0,8769, com.android.updater, 952680005, transmissão de intenção { act = android.intent.action.BOOT_COMPLETED flg = 0x9000010 cmp = com.android.updater/ .BootCompletedReceiver (tem extras) }]

O horário em que o ANR ocorreu é am_anr. O ponto no tempo é 12-17 06:02:14.463. Continue examinando o registro.

12-17 06:02:00.370 1566 1583 W BroadcastQueue: Tempo limite da transmissão BroadcastRecord{21ef8c2 u0 android.intent.action.BOOT_COMPLETED} - receiver=android.os.BinderProxy@2a6c365, iniciado 60006ms atrás 
12-17 06:02:00.370 1566 1583 W BroadcastQueue: Receptor durante o tempo limite: ResolveInfo{5a8283a com.android.updater/.BootCompletedReceiver m=0x108000} 
12-17 06:02:00.370 1566 1583 I am_broadcast_discard_app: [0,35584194,android.intent. ação.BOOT_COMPLETED, 49,ResolveInfo{5a8283a com.android.updater/.BootCompletedReceiver m=0x108000}]

No entanto, descobrimos que o ANR ocorreu entre 12-17 06:02:00.370, indicando que o horário no log de eventos é um valor aproximado e pode haver um certo grau de atraso devido à escassez de recursos do sistema. Como é a transmissão android.intent.action.BOOT_COMPLETED que recebe o ANR, podemos seguir as pistas.

12-17 06:01:00.383 1566 3524 I ActivityManager: Iniciar proc 8769:com.android.updater/9802 para transmissão com.android.updater/.BootCompletedReceiver caller=null

O processo de transmissão foi iniciado às 12-17 06:01:00.383

12-17 06:01:36.721 8769 8769 D BootCompletedReceiver: onReceive android.intent.action.BOOT_COMPLETED 
12-17 06:02:14.725 8769 8769 D UpdateService: onCreate

Às 12-17 06:01:36.721, o método onReceiver do cliente BootCompletedReceiver inicia o retorno de chamada, então onReceive inicia UpdateService e o tempo para chamar UpdateService.onCreate é 12-17 06:02:14.725. Com base na análise acima, há duas questões preliminares.

A transmissão começou às 12-17 06:01:00.383, o método onReceiver da transmissão iniciou o retorno de chamada às 12-17 06:01:36.721, e o horário ANR foi às 12-17 06:02:00.370, então por que isso iniciar 36 segundos depois? Acabei de receber a transmissão de inicialização concluída, o que é anormal por si só. Em segundo lugar, por que leva quase mais de um minuto para iniciar o UpdateService por meio da transmissão? Depois de analisar este ponto, os alunos do App acham que é impossível analisar mais a fundo, e 80% disso se deve ao sistema. A julgar pelas estatísticas da CPU, acredita-se que seja causado pelo uso excessivo de determinados programas, e o seguinte log é postado.

12-17 06:02:19.286 1566 1583 E ActivityManager: ANR em com.android.updater 
12-17 06:02:19.286 1566 1583 E ActivityManager: PID: 8769 
12-17 06:02:19.286 1566 1583 E ActivityManager: Motivo : Transmissão de Intent { act=android.intent.action.BOOT_COMPLETED flg=0x9000010 cmp=com.android.updater/.BootCompletedReceiver (tem extras) } 
12-17 06:02:19.286 1566 1583 E ActivityManager: Carregar: 0,0/0,0 / 0,0 
12-17 06: 02: 19.286 1566 1583 E ActivityManager: uso da CPU de 0 ms a 18.846 ms depois (2017-12-17 06: 02: 00.379 a 2017-12-17 06: 02: 19.224): 12-17 
06 :02:19.286 1566 1583 E ActivityManager: 195% 6142/com.immomo.momo: 195% usuário + 0% kernel 
12-17 06:02:19.286 1566 1583 E ActivityManager: 2,3% 8170/com.tencent.mm: 2,3 % usuário + 0% kernel/falhas: 448 menores
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,7% 1566/system_server: 0,4% usuário + 0,3% kernel/falhas: 150 menores 1 principais 12-17 06:02:19.286 1566 1583 E ActivityManager: 0,4% 90 
/ kworker/u16:3: 0% usuário + 0,4% kernel 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,3% 4704/com.tencent.mm:push: 0,1% usuário + 0,2% kernel / falhas: 116 menores 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,3% 8769/com.android.updater: 0,2% usuário + 0,1% kernel / falhas: 1600 menor 2 principal 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,2% 4790/com.tencent.mm:patch: 0,2% usuário + 0% kernel/falhas: 748 menores 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,2% 329/mmc-cmdqd/0: 0% usuário + 0,2% de núcleo
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,2% 5429/com.tencent.mm:push: 0% usuário + 0,1% kernel / falhas: 17 menores 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,2% 5435/com.tencent.mm:patch: 0,2% usuário + 0% kernel/falhas: 82 menores 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,2% 8712/com.tencent.mm:exdevice: 0,1 % usuário + 0% kernel 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,1% 432/logd: 0,1% usuário + 0% kernel / falhas: 4 menores 12-17 06:02:19.286 1566 1583 
E ActivityManager: 0,1% 844/msm_irqbalance: 0% usuário + 0,1% kernel/falhas: 4 menores 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,1% 7580/kworker/u16:2: 0% usuário + 0,1% kernel
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,1% 7/rcu_preempt: 0% usuário + 0,1% kernel 12-17 06:02:19.286 1566 
1583 E ActivityManager: 0,1% 1240/zygote: 0% usuário + 0,1 % kernel/falhas: 84 menores 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0% 3216/com.xiaomi.simactivate.service: 0% usuário + 0% kernel/falhas: 5 menores 
12-17 06:02 :19.286 1566 1583 E ActivityManager: 0,1% 8645/kworker/7:0: 0% usuário + 0,1% kernel 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0,1% 8730/kworker/4:2: 0% usuário + 0,1% kernel 
12-17 06:02:19.286 1566 1583 E ActivityManager: 0% 45/rcuop/4: 0% usuário + 0% kernel

No entanto, a ocupação da CPU de 195% não é alta. Em multi-core, a ocupação máxima de cada núcleo é 100% (a ocupação de oito núcleos é 800% ). Em segundo lugar, Carga: 0,0 / 0,0 / 0,0. A carga não é ativo durante 15 minutos. É 0. Está parado? Parece que este Log não está totalmente correto. No entanto, nos telefones Xiaomi, o monitoramento ANR será fortalecido e o seguinte Log será gerado.

12-17 06:02:14.693 8769 8769 W MIUI-BLOCK-MONITOR: A mensagem {quando=-36s107ms what=113 obj=ReceiverData{intent=Intent { act=android.intent.action.BOOT_COMPLETED flg=0x9000010 cmp=com .android.updater/.BootCompletedReceiver (tem extras) } packageName=com.android.updater resultCode=0 resultData=null resultExtras=null} target=android.app.ActivityThread$H planTime=1513461660613 dispatchTime=1513461696720 finishTime=0 } levou 74080ms e levou 37.973 ms após o envio.

Além disso, registramos os pontos no tempo de cada status de cada Mensagem para facilitar nossa análise.

  • quando: o tempo desde o momento em que a mensagem deve ser executada até o momento em que anr ocorre
  • planTime: o momento em que o plano de mensagem é executado
  • dispatchTime: o momento em que a mensagem é realmente executada
  • finishTime: O ponto no tempo em que a mensagem é concluída.
    Calcule o tempo de execução da mensagem como: -when-(dispatchTime-planTime)=0, então o que isso significa? Isso significa que a Mensagem 113 estava prestes a começar a ser executada, mas ocorreu um ANR antes de iniciar a execução. Ela aguardou 36 segundos na fila de mensagens do Looper do thread principal. Não há rastro do thread principal neste log e não tem efeito porque pode-se observar que esta mensagem ainda não foi executada? Então, o que você está fazendo durante esses 36 segundos? Existem mais registros abaixo.
12-17 06: 01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: A chamada do fichário levou 3.973 ms. 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: java.lang.Throwable 12-17 06:01 
:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.os.AnrMonitor.checkBinderCallTime(AnrMonitor. java: 591) 
12-17 06: 01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.os.BinderProxy.transact (Binder.java: 623) 12-17 06: 01: 
29.334 8769 8769 W MIUI-BLOCK -MONITOR: em android.content.pm.IPackageManager$Stub$Proxy.getApplicationInfo(IPackageManager.java:2658) 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app.ApplicationPackageManager.getApplicationInfoAsUser( ApplicationPackageManager.java:340)
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app.ApplicationPackageManager.getApplicationInfo(ApplicationPackageManager.java:333) 12-17 06:01: 
29.334 8769 8769 W MIUI-BLOCK-MONITOR: em miui.core.ManifestParser.create (SourceFile: 64) 
12-17 06: 01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: em miui.core.SdkManager.start (SourceFile: 186) 
12-17 06: 01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: em java.lang.reflect.Method.invoke (Método Nativo) 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em miui.external.a.abx() 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em miui.external.a.attachBaseContext() 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app.Application .attach(Application.java:193)
12-17 06: 01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app.Instrumentation.newApplication (Instrumentation.java: 1009) 12-17 06: 01: 
29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app.Instrumentation.newApplication(Instrumentation.java:993) 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app.LoadedApk.makeApplication(LoadedApk.java:800) 
12-17 06 :01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app.ActivityThread.handleBindApplication(ActivityThread.java:5471) 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app. ActivityThread.-wrap2(ActivityThread.java) 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app.ActivityThread$H.handleMessage(ActivityThread.java:1584)
12-17 06: 01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.os.Handler.dispatchMessage (Handler.java: 102) 12-17 06: 01: 
29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.os.Looper.loop (Looper.java: 163) 
12-17 06: 01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: em android.app.ActivityThread.main (ActivityThread.java: 6221) 
12-17 06 :01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em java.lang.reflect.Method.invoke (método nativo) 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em com.android.internal .os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) 
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: em com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794 )

A operação bindApplication está sendo executada durante os 36 segundos. Neste caso, é mais provável que o status do sistema não seja otimista neste momento. Em segundo lugar, através da análise acima, também podemos ver que o onReceiver do BootCompletedReceiver é processado no thread principal, e iniciar o serviço também leva tempo. Depois de gastar muito tempo, também podemos considerar especificar o manipulador ao registrar o receptor e deixar o onReceiver rodar no thread filho (como fazer isso, você pode ver o código-fonte )

4. Rotinas de análise para problemas de ANR

  • Pegue o relatório de bug, procure por ANR, verifique a hora e o processo de ocorrência e veja se há algum problema com a carga da CPU.
  • Pesquise o rastreamento do thread principal de acordo com o processo e encontre o local bloqueado. Se for uma chamada do Binder, confirme ainda a situação do extremo oposto; se for uma operação demorada, modifique-a diretamente para assíncrona. Se você Se você suspeitar que a execução do sistema está lenta, você pode verificar binder_sample, dvm_lock e outras informações., Em segundo lugar, se há muitos gcs e se lmk mata processos com frequência, pode informar o status de integridade do sistema.
  • Análise e solução baseada em código fonte

Este artigo registra apenas alguns casos e métodos de análise. A ideia norteadora é descobrir por que o thread principal foi bloqueado no passado. De um modo geral, é relativamente fácil de dominar. Ainda não abordou os princípios específicos, como o princípio de despejo do ANR, como o sistema determina o ANR, o que fazer com traços inválidos de ANR e outras questões mais aprofundadas. . Como os problemas de ANR às vezes são uma dor de cabeça, o rastreamento pode não ser a primeira cena do crime. Alguns fabricantes de telefones celulares reforçaram o monitoramento de ANRs, o que pode gerar mais informações e melhorar a eficiência da análise de problemas de ANR. Além disso, também pode ser vimos que os alunos que trabalham com questões de ANR no Room ficarão mais confortáveis ​​devido à experiência na leitura de código-fonte no trabalho.

Acho que você gosta

Origin blog.csdn.net/weixin_47465999/article/details/129664103
Recomendado
Clasificación