Existe uma maneira de descobrir onde meu aplicativo lançou um ANR (aplicativo não está respondendo). Dei uma olhada no arquivo traces.txt em / data e vejo um rastreamento para o meu aplicativo. É isso que vejo no traço.
DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
| group="main" sCount=1 dsCount=0 s=0 obj=0x400143a8
| sysTid=691 nice=0 sched=0/0 handle=-1091117924
at java.lang.Object.wait(Native Method)
- waiting on <0x1cd570> (a android.os.MessageQueue)
at java.lang.Object.wait(Object.java:195)
at android.os.MessageQueue.next(MessageQueue.java:144)
at android.os.Looper.loop(Looper.java:110)
at android.app.ActivityThread.main(ActivityThread.java:3742)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
at dalvik.system.NativeStart.main(Native Method)
"Binder Thread #3" prio=5 tid=15 NATIVE
| group="main" sCount=1 dsCount=0 s=0 obj=0x434e7758
| sysTid=734 nice=0 sched=0/0 handle=1733632
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #2" prio=5 tid=13 NATIVE
| group="main" sCount=1 dsCount=0 s=0 obj=0x433af808
| sysTid=696 nice=0 sched=0/0 handle=1369840
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #1" prio=5 tid=11 NATIVE
| group="main" sCount=1 dsCount=0 s=0 obj=0x433aca10
| sysTid=695 nice=0 sched=0/0 handle=1367448
at dalvik.system.NativeStart.run(Native Method)
"JDWP" daemon prio=5 tid=9 VMWAIT
| group="system" sCount=1 dsCount=0 s=0 obj=0x433ac2a0
| sysTid=694 nice=0 sched=0/0 handle=1367136
at dalvik.system.NativeStart.run(Native Method)
"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
| group="system" sCount=0 dsCount=0 s=0 obj=0x433ac1e8
| sysTid=693 nice=0 sched=0/0 handle=1366712
at dalvik.system.NativeStart.run(Native Method)
"HeapWorker" daemon prio=5 tid=5 VMWAIT
| group="system" sCount=1 dsCount=0 s=0 obj=0x4253ef88
| sysTid=692 nice=0 sched=0/0 handle=1366472
at dalvik.system.NativeStart.run(Native Method)
----- end 691 -----
Como posso descobrir onde está o problema? Os métodos no rastreamento são todos os métodos do SDK.
Obrigado.
android
performance
android-anr-dialog
lostInTransit
fonte
fonte
android.os.MessageQueue.nativePollOnce(Native Method)
. Posso ignorá-lo com segurança?Respostas:
Um ANR acontece quando alguma operação longa ocorre no encadeamento "principal". Esse é o encadeamento do loop de eventos e, se estiver ocupado, o Android não poderá processar mais eventos da GUI no aplicativo e, portanto, exibirá uma caixa de diálogo ANR.
Agora, no rastreamento que você postou, o thread principal parece estar indo bem, não há problema. Ele está ocioso no MessageQueue, aguardando a chegada de outra mensagem. No seu caso, o ANR provavelmente foi uma operação mais longa, em vez de algo que bloqueou o encadeamento permanentemente; portanto, o encadeamento de eventos se recuperou após o término da operação e seu rastreamento passou. após o ANR.
Detectar onde os ANRs acontecem é fácil se for um bloco permanente (conflito obtendo alguns bloqueios por exemplo), mas mais difícil se for apenas um atraso temporário. Primeiro, repasse seu código e procure por pontos remuneráveis e operações de longa duração. Os exemplos podem incluir o uso de soquetes, bloqueios, suspensão de linha e outras operações de bloqueio de dentro da linha de eventos. Você deve garantir que tudo isso ocorra em threads separados. Se nada parecer o problema, use DDMS e ative a exibição do encadeamento. Isso mostra todos os threads em seu aplicativo semelhantes ao rastreamento que você possui. Reproduza o ANR e atualize o thread principal ao mesmo tempo. Isso deve mostrar exatamente o que está acontecendo no momento da ANR
fonte
Você pode ativar o StrictMode no nível 9 da API e acima.
fonte
Você está se perguntando qual tarefa contém um thread da interface do usuário. O arquivo de rastreamento fornece uma dica para encontrar a tarefa. você precisa investigar um estado de cada thread
Estado do encadeamento
Concentre-se no estado SUSPENDED, MONITOR. O estado do monitor indica qual thread é investigado e o estado SUSPENDED do thread é provavelmente o principal motivo do conflito.
Etapas básicas de investigação
o rastreio nem sempre contém "aguardando bloqueio". neste caso, é difícil encontrar o motivo principal.
fonte
- waiting to lock an unknown object
dentro"HeapTaskDaemon" daemon prio=5 tid=8 Blocked
. O que significa alguém pode ajudar?Eu tenho aprendido android nos últimos meses, por isso estou longe de ser um especialista, mas fiquei muito decepcionado com a documentação sobre ANRs.
A maioria dos conselhos parece ter como objetivo evitá-los ou corrigi-los, examinando cegamente seu código, o que é ótimo, mas não consegui encontrar nada sobre a análise do rastreamento.
Há três coisas que você realmente precisa procurar nos logs ANR.
1) Deadlocks: quando um thread está no estado WAIT, você pode ver os detalhes para descobrir quem é "holdby =". Na maioria das vezes, ele será mantido por si só, mas se for mantido por outro segmento, é provável que seja um sinal de perigo. Vá olhar para esse tópico e veja o que ele contém. Você pode encontrar um loop, que é um sinal claro de que algo deu errado. Isso é muito raro, mas é o primeiro ponto, porque quando isso acontece, é um pesadelo
2) Linha principal em espera: se sua linha principal estiver no estado WAIT, verifique se ela está retida por outra linha. Isso não deve acontecer, porque o thread da interface do usuário não deve ser mantido por um thread em segundo plano.
Ambos os cenários significam que você precisa refazer seu código significativamente.
3) Operações pesadas no thread principal: esta é a causa mais comum de ANRs, mas às vezes é uma das mais difíceis de encontrar e corrigir. Veja os detalhes principais do thread. Role para baixo o rastreamento da pilha e até ver as classes que você reconhece (do seu aplicativo). Observe os métodos no rastreamento e descubra se você está fazendo chamadas de rede, chamadas de banco de dados, etc. nesses locais.
Finalmente, e peço desculpas por conectar descaradamente meu próprio código, você pode usar o analisador de logs python que escrevi em https://github.com/HarshEvilGeek/Android-Log-Analyzer Isso examinará seus arquivos de log, abrirá arquivos ANR, encontre deadlocks, encontre threads principais em espera, encontre exceções não capturadas nos logs do agente e imprima tudo na tela de uma maneira relativamente fácil de ler. Leia o arquivo Leia-me (que vou adicionar) para saber como usá-lo. Isso me ajudou muito na semana passada!
fonte
Sempre que você está analisando problemas de tempo, a depuração geralmente não ajuda, pois congelar o aplicativo em um ponto de interrupção fará com que o problema desapareça.
Sua melhor aposta é inserir muitas chamadas de log (Log.XXX ()) nos diferentes threads e retornos de chamada do aplicativo e ver onde está o atraso. Se você precisar de um rastreamento de pilha, crie uma nova exceção (apenas instancia uma) e registre-a.
fonte
O que dispara o ANR?
Geralmente, o sistema exibe um ANR se um aplicativo não puder responder à entrada do usuário.
Em qualquer situação em que seu aplicativo execute uma operação potencialmente longa, você não deve executar o trabalho no thread da interface do usuário, mas criar um thread de trabalho e executar a maior parte do trabalho lá. Isso mantém o thread da interface do usuário (que aciona o loop de eventos da interface do usuário) em execução e evita que o sistema conclua que seu código congelou.
Como evitar ANRs
Aplicativos Android normalmente são executados inteiramente em um único thread, por padrão, o "thread da interface do usuário" ou "thread principal"). Isso significa que qualquer coisa que seu aplicativo esteja fazendo no encadeamento da interface do usuário que leva muito tempo para concluir pode acionar a caixa de diálogo ANR porque o aplicativo não está dando a si mesmo a chance de manipular o evento de entrada ou as transmissões de intenção.
Portanto, qualquer método executado no thread da interface do usuário deve fazer o mínimo possível de trabalho nesse thread. Em particular, as atividades devem fazer o mínimo possível para configurar os principais métodos de ciclo de vida, como onCreate () e onResume (). Operações potencialmente demoradas, como operações de rede ou banco de dados, ou cálculos computacionalmente caros, como redimensionar bitmaps, devem ser feitos em um encadeamento de trabalho (ou no caso de operações de bancos de dados, por meio de uma solicitação assíncrona).
Código: thread de trabalho com a classe AsyncTask
Código: Executar segmento do Trabalhador
Para executar este segmento de trabalho, basta criar uma instância e chamar execute ():
Fonte
http://developer.android.com/training/articles/perf-anr.html
fonte
meu problema com o ANR, depois de muito trabalho, descobri que um thread estava chamando um recurso que não existia no layout, em vez de retornar uma exceção, recebi o ANR ...
fonte
Você precisa procurar por "aguardando bloqueio" no arquivo /data/anr/traces.txt
para obter mais detalhes: engenheiro de alto desempenho com ferramentas do Android & Play (Google I / O '17)
fonte
Básico na resposta @Horyun Lee, escrevi um pequeno script python para ajudar a investigar o ANR de
traces.txt
.Os ANRs serão exibidos como gráficos
graphviz
se você tiver instaladograpvhviz
no seu sistema.Um png será exibido como abaixo se houver ANRs detectados no arquivo
traces.txt
. É mais intuitivo.O
traces.txt
arquivo de exemplo usado acima foi obtido daqui .fonte
Considere usar a biblioteca ANR-Watchdog para rastrear e capturar com precisão os rastreamentos de pilha ANR em um alto nível de detalhe. Você pode enviá-los para sua biblioteca de relatórios de falhas. Eu recomendo usar
setReportMainThreadOnly()
neste cenário. Você pode fazer com que o aplicativo lance uma exceção não fatal do ponto de congelamento ou faça com que o aplicativo seja encerrado quando o ANR acontecer.Observe que os relatórios ANR padrão enviados ao console do desenvolvedor do Google Play geralmente não são precisos o suficiente para identificar o problema exato. É por isso que é necessária uma biblioteca de terceiros.
fonte