Gravar e visualizar registros com o Logcat

A janela Logcat no Android Studio exibe mensagens do sistema, como quando ocorre uma coleta de lixo, e mensagens que você adicionou ao seu app com a classe Log. Ela exibe mensagens em tempo real e mantém um histórico para que você possa ver mensagens mais antigas.

Para exibir apenas as informações do seu interesse, você pode criar filtros, determinar quantas informações aparecerão nas mensagens, definir níveis de prioridade, exibir apenas mensagens produzidas pelo código do app e fazer uma pesquisa pelo registro. Por padrão, o Logcat mostra a saída de registro relacionada apenas ao app executado mais recentemente.

Quando um app gera uma exceção, o Logcat mostra uma mensagem seguida do rastreamento de pilha associado contendo links para a linha de código.

A partir do Android Studio 2.2, a janela Run também exibe mensagens de registro para o app em execução. Você pode configurar a exibição da saída do logcat, mas não a janela Run.

Ver registros do app

Para exibir as mensagens de registro de um app:

  1. Crie e execute seu app em um dispositivo.
  2. Clique em View > Tool Windows > Logcat (ou clique em Logcat na barra da janela de ferramentas).

A janela "Logcat" mostra as mensagens de registro do app selecionado, conforme escolhido nas listas suspensas na parte superior da janela (mostrado na Figura 1).

Figura 1. Janela "Logcat"

Por padrão, o Logcat exibe apenas as mensagens de registro do app em execução no dispositivo. Para alterar esse padrão, veja como filtrar mensagens do Logcat.

A barra de ferramentas do Logcat apresenta os seguintes botões:

  1. Clear logcat : clique para limpar o registro visível.
  2. Scroll to the end : clique para pular para o final do registro e ver as mensagens mais recentes. Se você clicar em uma linha no registro, a exibição pausará a rolagem nesse ponto.
  3. Up the stack trace e Down the stack trace : clique para navegar para cima e para baixo nos rastreamentos de pilha no registro, selecionando os nomes de arquivo subsequentes (e vendo os números de linha correspondentes no editor) que aparecem nas exceções impressas. Esse é o mesmo comportamento de quando você clica em um nome de arquivo no registro.
  4. Use soft wraps : clique para ativar a quebra de linha e impedir a rolagem horizontal (embora qualquer string inquebrável ainda exija rolagem horizontal).
  5. Print : clique para imprimir as mensagens do Logcat. Depois de selecionar suas preferências de impressão na caixa de diálogo exibida, você também pode optar por salvar como um PDF.
  6. Restart : clique para limpar o registro e reiniciar o Logcat. Ao contrário do botão Clear logcat, esse recupera e exibe mensagens de registro anteriores. Por isso, ele é mais útil se o Logcat não responder e você não quiser perder suas mensagens de registro.
  7. Logcat header : clique para abrir a caixa de diálogo Configure Logcat Header, onde é possível personalizar a aparência de cada mensagem do Logcat, como mostrar a data e a hora.
  8. Screen capture : clique para criar uma captura de tela.
  9. Screen record : clique para gravar um vídeo do dispositivo (por no máximo três minutos).

Escrever mensagens de registro

A classe Log permite que você crie mensagens de registro que aparecem no Logcat. Geralmente, são usados os seguintes métodos de registro, listados em ordem decrescente de prioridade (ou de menos para mais detalhado):

Consulte a descrição da classe Log para ver uma lista mais completa de opções.

Nunca compile registros detalhados no seu app, exceto durante o desenvolvimento. Registros de depuração são compilados, mas eliminados no tempo de execução, enquanto que os registros de erro, aviso e informações sempre são mantidos.

Para cada método de registro, o primeiro parâmetro precisa ser uma tag exclusiva e o segundo, uma mensagem. A tag de uma mensagem de registro do sistema é uma string curta que indica o componente do sistema a partir do qual a mensagem é originada (por exemplo, ActivityManager). A tag pode ser qualquer string que você achar útil, como o nome da classe atual.

Uma boa prática geral é declarar uma constante TAG na classe para usar no primeiro parâmetro. Por exemplo, você pode criar uma mensagem de registro de informação desta forma:

Kotlin

    private const val TAG = "MyActivity"
    ...
    Log.i(TAG, "MyClass.getView() — get item number $position")
    

Java

    private static final String TAG = "MyActivity";
    ...
    Log.i(TAG, "MyClass.getView() — get item number " + position);
    

Observação: os nomes de tag com mais de 23 caracteres são truncados na saída do Logcat.

Formato das mensagens do Logcat

Cada mensagem do registro do Android é associada a uma tag e uma prioridade. A tag de uma mensagem de registro do sistema é uma string curta que indica o componente do sistema a partir do qual a mensagem é originada (por exemplo, ActivityManager). Uma tag definida pelo usuário pode ser qualquer string que você achar útil, como o nome da classe atual (a tag recomendada). Você pode defini-la chamando o método Log, por exemplo:

Kotlin

    Log.d(tag, message)
    

Java

    Log.d(tag, message);
    

A prioridade é um dos seguintes valores:

  • V: detalhado (prioridade mais baixa)
  • D: depuração
  • I: informações
  • W: aviso
  • E: erro
  • A: afirmação

O formato das mensagens do registro é:

    date time PID-TID/package priority/tag: message
    

Por exemplo, a mensagem de registro a seguir tem prioridade V e uma tag AuthZen:

    12-10 13:02:50.071 1901-4229/com.google.android.gms V/AuthZen: Handling delegate intent.
    

O PID se refere ao identificador do processo e o TID é o identificador da linha de execução: eles podem ser iguais se só houver uma linha de execução.

Configurar o nível do registro

Você pode controlar quantas mensagens aparecem no Logcat definindo o nível de registro. Você pode exibir todas as mensagens ou apenas aquelas que indicam as situações mais graves.

Lembre-se de que o Logcat continua a coletar todas as mensagens, independentemente da configuração do nível de registro. A configuração determina apenas o que o Logcat exibe.

No menu "Log level", selecione um dos valores a seguir:

  • Verbose (detalhado): exibe todas as mensagens de registro (padrão).
  • Debug (depuração): exibe as mensagens de registro da depuração que são úteis apenas durante o desenvolvimento, além de mensagens de nível inferior dessa lista.
  • Info (informações): exibe mensagens de registro esperadas para uso regular, além de mensagens de nível inferior dessa lista.
  • Warn (aviso): exibe possíveis problemas que ainda não são erros, além de mensagens de nível inferior dessa lista.
  • Error (erro): exibe problemas que causaram erros, além de mensagens de nível inferior dessa lista.
  • Assert (afirmação): exibe problemas que o desenvolvedor acredita que nunca acontecerão.

Pesquisar mensagens do Logcat

Para pesquisar as mensagens atualmente exibidas no Logcat:

  1. Você pode selecionar Regex se quiser usar um padrão de pesquisa de expressão regular.
  2. Digite uma sequência de caracteres no campo de pesquisa .

    A exibição da saída do Logcat é alterada conforme necessário.

  3. Pressione Enter para armazenar a string de pesquisa no menu durante essa sessão.
  4. Para repetir a pesquisa, selecione-a no menu de pesquisa. Marque ou desmarque Regex caso seja necessário (a configuração não é gravada).

Filtrar mensagens do Logcat

Uma forma de reduzir a saída de registros a um nível gerenciável é restringi-la com um filtro.

Observação: o filtro se aplica ao seu histórico completo do Logcat, não apenas às mensagens atualmente exibidas no Logcat. Veja se as outras opções de exibição estão configuradas corretamente para poder ver a saída do filtro que você quer examinar.

Para definir e aplicar um filtro:

  1. No menu de filtragem, selecione uma opção de filtro:
    • Show only selected application: exibe somente as mensagens produzidas pelo código do app (padrão). O Logcat filtra as mensagens de registro usando o PID do app ativo.
    • No Filters: não aplica filtros. O Logcat exibe todas as mensagens de registro do dispositivo, independentemente do processo selecionado.
    • Edit Filter Configuration: cria ou modifica um filtro personalizado. Por exemplo, você pode criar um filtro para ver mensagens de registro de dois apps ao mesmo tempo.

    Depois de definir os filtros, você pode selecioná-los no menu. Para removê-los do menu, basta excluí-los.

  2. Se você escolheu Edit Filter Configuration, crie ou modifique um filtro.
    1. Especifique os parâmetros do filtro na caixa de diálogo Create New Logcat Filter:
      • Filter Name: digite o nome de um filtro que você queira definir ou selecione um no painel esquerdo para modificá-lo. O nome pode conter apenas caracteres minúsculos, sublinhados e dígitos.
      • Log Tag: permite especificar uma tag. Para mais informações, acesse Formato das mensagens do Logcat.
      • Log Message: permite especificar o texto da mensagem de registro. Para mais informações, acesse Formato das mensagens do Logcat.
      • Package Name: permite especificar o nome de um pacote. Para mais informações, acesse Formato das mensagens do Logcat.
      • PID: permite especificar um ID de processo. Para mais informações, acesse Formato das mensagens do Logcat.
      • Log Level: permite selecionar um nível de registro. Para mais informações, consulte Definir o nível de registro.
      • Regex: selecione essa opção para usar uma sintaxe de expressão regular para esse parâmetro.
    2. Clique em + para adicionar a configuração de filtro no painel esquerdo.

      Para remover um filtro, selecione-o no painel esquerdo e clique em -.

    3. Quando terminar, clique em OK.

Se você acha que não consegue ver as mensagens de registro que gostaria, tente selecionar No filters e pesquisar mensagens de registro específicas.

Ler mensagens de coleta de lixo

Às vezes, quando ocorre um evento de coleta de lixo, elas são impressas no Logcat.

Para mais detalhes sobre a memória do app, use o Memory Profiler.

Mensagens de registro da Dalvik

Na Dalvik (mas não na ART), toda coleta de lixo (GC, na sigla em inglês) imprime as seguintes informações no Logcat:

    D/dalvikvm(PID): GC_Reason Amount_freed, Heap_stats, External_memory_stats, Pause_time
    

Exemplo:

    D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms
    
Motivo da GC
O que desencadeou a GC e o tipo da coleção. Estes são alguns dos motivos possíveis:
GC_CONCURRENT
Uma GC simultânea que libera memória à medida que o heap começa a ficar cheio.
GC_FOR_MALLOC
Uma GC foi causada porque o app tentou alocar memória quando o heap já estava cheio e, por isso, o sistema teve que parar o app e recuperar memória.
GC_HPROF_DUMP_HEAP
Uma GC que ocorre quando você solicita a criação de um arquivo HPROF para analisar o heap.
GC_EXPLICIT
Uma GC explícita, como quando você chama gc(), que você precisa evitar chamar e, em vez disso, confiar que a GC será executada no momento certo.
GC_EXTERNAL_ALLOC
Isso acontece somente na API de nível 10 e anteriores (as versões mais recentes alocam tudo no heap da Dalvik). Uma GC da memória alocada externamente, como os dados de pixel armazenados na memória nativa ou em buffers de byte NIO.
Quantidade liberada
A quantidade de memória recuperada por essa GC.
Estatísticas de heap
Percentual livre do heap e (número de objetos ativos)/(tamanho total do heap).
Estatística da memória externa
Memória alocada externamente em API de nível 10 ou anterior (quantidade de memória alocada) / (nível a partir do qual a coleta ocorre).
Tempo de pausa
Heaps maiores terão um tempo de pausa maior. Os tempos de pausa simultâneos mostram duas pausas: uma no início da coleta e outra perto do fim.

Enquanto essas mensagens de registro se acumulam, procure identificar aumentos na estatística do heap (o valor 3571K/9991K no exemplo acima). Se esse valor continuar aumentando, é possível que haja um vazamento de memória.

Mensagens de registro da ART

Ao contrário da Dalvik, a ART não registra mensagens para GCs que não forem solicitadas explicitamente. As GCs são impressas apenas quando são consideradas lentas. Mais precisamente, se a pausa da GC exceder 5 ms ou a duração dela exceder 100 ms. Se o app não estiver em um estado perceptível de pausa, por exemplo, quando o app estiver em segundo plano e o usuário não puder perceber uma pausa da GC, nenhuma GC será considerada lenta. GCs explícitas sempre são registradas.

A ART oferece as seguintes informações nas mensagens de registro das coletas de lixo:

    I/art: GC_Reason GC_Name Objects_freed(Size_freed) AllocSpace Objects,
        Large_objects_freed(Large_object_size_freed) Heap_stats LOS objects, Pause_time(s)
    

Exemplo:

    I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace objects,
        21(416KB) LOS objects, 33% free, 25MB/38MB, paused 1.230ms total 67.216ms
    
Motivo da GC
O que desencadeou a GC e o tipo da coleção. Estes são alguns dos motivos possíveis:
Concurrent
Uma GC simultânea que não suspende as linhas de execução do app. Essa GC é executada em uma linha de execução em segundo plano e não impede alocações.
Alloc
GC iniciada porque o app tentou alocar memória quando o heap já estava cheio. Nesse caso, a coleta de lixo ocorreu na linha de execução de alocação.
Explicit
A coleta de lixo foi solicitada explicitamente por um app, por exemplo, chamando gc() ou gc(). Assim como na Dalvik, a prática recomendada na ART é confiar na GC e evitar solicitar GCs explícitas, se possível. GCs explícitas não são recomendadas porque bloqueiam a linha de execução de alocação e gastam ciclos de CPU desnecessariamente. As GCs explícitas também podem gerar instabilidade (repetições involuntárias, inconstância ou lentidão no app) se causarem a interrupção forçada de outras linhas de execução.
NativeAlloc
A coleta foi causada pela pressão da memória nativa por parte das alocações nativas, como os objetos de alocação Bitmaps ou RenderScript.
CollectorTransition
A coleta foi ocasionada por uma transição de heap. Isso é causado pela alteração da estratégia da GC no tempo de execução (como quando o app muda entre estados perceptíveis de pausa). As transições do coletor consistem em copiar todos os objetos de um espaço apoiado por lista livre para um espaço de ponteiro de incremento simples (ou vice-versa).

Isso ocorre apenas em dispositivos com pouca RAM e anteriores ao Android 8.0 quando um app altera os estados do processo de um estado de pausa perceptível (como quando o app está em primeiro plano, onde o usuário pode perceber uma pausa da GC) para um estado não pausado perceptível (ou vice-versa).

HomogeneousSpaceCompact
A compactação homogênea de espaço é a mudança de espaço de lista livre para compactação de espaço de lista livre que normalmente ocorre quando um app é movido para um estado de pausa imperceptível do processo. Os principais motivos que levam a isso são a redução do uso de RAM e a desfragmentação do heap.
DisableMovingGc
Esse não é um motivo real da GC, mas uma observação de que a coleta foi bloqueada devido ao uso de GetPrimitiveArrayCritical enquanto a compactação de heap simultânea está ocorrendo. Em geral, o uso de GetPrimitiveArrayCritical não é recomendado de forma alguma em virtude das restrições aos coletores de movimento.
HeapTrim
Esse não é um motivo de GC, mas uma observação de que a coleta está bloqueada até o corte do heap acabar.
Nome da GC
A ART tem diversas GCs que você pode executar.
Concurrent mark sweep (CMS)
Um coletor de todo o heap que coleta livremente todos os espaços, menos o espaço de imagem.
Concurrent partial mark sweep
Um coletor de quase todo o heap que coleta todos os espaços, menos os espaços de imagem e zigoto.
Concurrent sticky mark sweep
Um coletor geracional que só consegue liberar objetos alocados desde a última GC. Essa coleta de lixo é executada com mais frequência do que uma mark sweep completa ou parcial, já que é mais rápida e tem pausas mais curtas.
Marksweep + semispace
Uma GC não simultânea de cópia usada para transições do heap e para compactação homogênea de espaços (para desfragmentar o heap).
Objetos liberados
O número de objetos que foram recuperados por essa GC do espaço dos objetos não grandes.
Volume liberado
O número de bytes que foram recuperados por essa GC do espaço dos objetos não grandes.
Objetos grandes liberados
O número de objetos no espaço de objetos grandes que foram recuperados por essa coleta de lixo.
Volume liberado dos objetos grandes
O número de bytes no espaço de objetos grandes que foram recuperados por essa coleta de lixo.
Estatísticas de heap
Percentual livre e (número de objetos ativos)/(tamanho total do heap).
Tempos de pausa
Em geral, os tempos de pausa são proporcionais ao número de referências a objeto que foram modificadas durante a execução da GC. No momento, as GCs de CMS da ART só têm uma pausa, que é próxima ao fim da GC. As GCs de movimento têm uma pausa longa que representa a maior parte da duração da GC.

Se você vê muitas GCs no Logcat, tente identificar aumentos na estatística do heap (o valor 25MB/38MB no exemplo acima). Se esse valor continuar aumentando e nunca parecer ficar menor, é possível que haja um vazamento de memória. Como alternativa, se vir a GC que ocorreu pelo motivo "Alloc", você já está operando perto da capacidade máxima do heap e pode esperar a ocorrência de exceções de falta de memória no futuro.