Analisar problemas de memória

Saiba como identificar a causa de problemas de memória do aplicativo Java. Você pode gerar um despejo de heap automática e manualmente, além de um histograma de heap, para identificar a causa.

Descrição description

Ambiente

Experience Manager

Problema/Sintomas

O aplicativo JAVA é executado mais lentamente e, por fim, fica sem memória ou você vê um erro nos logs ou na saída do console OutOfMemoryError: Java heap space ou OutOfMemoryError: gc overhead limit exceeded.

Resolução resolution

Causa
Esses problemas podem ter muitas causas.

Uma possível causa é que o aplicativo java, no nosso caso o CRX/CQ, foi iniciado a partir da linha de comando com as configurações padrão de memória heap do Java. Isso significa que o parâmetro jvm -Xmx não foi especificado. O CRX ou CQ precisa de pelo menos 256 MB de heap alocados para serem executados. Se esse for o problema, iniciando a partir da linha de comando, verifique se as configurações da memória heap estão definidas. Exemplo:

java -Xmx512m -jar *.jar

Se não for o caso, seu aplicativo pode estar retendo muitos objetos sem liberá-los para a coleta de lixo. Isso é chamado de vazamento de memória. Clique aqui para obter mais informações. Consulte a seção abaixo para ver como analisar problemas de memória em aplicativos java.
Criar despejo de heap:

Gerar um despejo de heap automaticamente

Para criar automaticamente um despejo de heap ao ficar sem memória, você pode adicionar o parâmetro jvm -XX:+HeapDumpOnOutOfMemoryError para gerar um despejo de heap automaticamente quando o aplicativo lança um OutOfMemoryError. Por exemplo,

java -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -jar *.jar

Isso gera um arquivo de despejo de heap (java_...hprof) no diretório de trabalho do processo sempre que o processo java fica sem memória. O processo pode continuar a ser executado depois que o despejo de heap foi gerado. Geralmente, um arquivo de despejo de heap é suficiente para analisar o problema.

Observação:  se estiver usando script crx-quickstart/server/start para iniciar sua instância do CRX, você pode adicionar -XX:+HeapDumpOnOutOfMemoryError para a variável CQ_JVM_OPTS (verifique se a variável também não está comentada). Por exemplo:

CQ_JVM_OPTS='-XX:+HeapDumpOnOutOfMemoryError'

Depois de adicionar esse parâmetro e reiniciar a instância do CRX, verifique se a nova opção jvm está definida. Executar o ps -ef | grep java na linha de comando. Em seguida, verifique se você vê -XX:+HeapDumpOnOutOfMemoryError como parâmetro do processo java do CRX.

Se você precisar especificar um diretório diferente para gerar o despejo de heap devido a restrições de espaço em disco, poderá adicionar o parâmetro -XX:HeapDumpPath=/path/to/generate/heapdump para informar ao jvm onde colocar o arquivo.

Consulte aqui para obter uma referência de parâmetros jvm relacionados à depuração.
Gerar um despejo de heap manualmente
Sun/Oracle JVM

Para gerar manualmente um despejo de heap, execute este comando (jmap e jps podem ser encontrados na pasta bin do seu diretório inicial jdk):

  1. procure a pid do processo java para a qual você está gerando um despejo de heap.

    • No Unix ou Linux isso pode ser feito com ps -ef | grep java ou jps -l
    • No Windows, isso pode ser feito abrindo o gerenciador de tarefas. Pressione Ctrl+Shift+Esc e vá para Exibir e, em seguida, vá para Selecionar Colunas e vá para PID (Identificador do Processo) ou jps -l
  2. Execute o comando jmap abaixo, substitua /path/to/generate/heapdumpfile.hprof pelo local em que você deseja gerar o arquivo de despejo de heap e substitua o 1234 pela pid que você pesquisou na etapa anterior.

    code language-none
    jmap -dump:format=b,file=/path/to/generate/heapdumpfile.hprof 1234
    

IBM JVM

Primeiro, você terá que alterar as configurações padrão da JVM em relação aos agentes de despejo para gerar os despejos corretos no sinal do usuário. Há vários tipos de despejos, mas você geralmente precisa do  despejo do sistema  completo para executar uma análise completa da memória. Adicione os seguintes argumentos:

Xdump:heap:opts=PHD+CLASSIC:events=user -Xdump:system:events=user

Esse evento de "usuário" acontece quando a JVM recebe o sinal SIGQUIT (Linux, AIX®, z/OS® e i5/OS™) ou SIGBREAK (Windows) do sistema operacional.

Para obter mais informações, consulte a documentação do fornecedor aqui.

Aviso: os arquivos de despejo de heap são grandes e podem ter até o mesmo tamanho no disco que a configuração máxima do parâmetro heap -Xmx jvm. Verifique se há espaço em disco suficiente alocado para o diretório onde o arquivo de despejo é gerado.
Analisar despejo de heap
Uma boa ferramenta para analisar despejos de heap é o EclipseMAT (Eclipse Memory Analyzer).

Esta ferramenta não pode analisar dumps gerados pelo  IBM JVM. Para eles, existem várias possibilidades. O IBM HeapAnalyzer funcionará bem para os despejos de heap no formato PHD ou clássico.

Para obter uma análise completa do despejo do sistema, use o Workbench do Assistente de Suporte da IBM, com as Ferramentas de Monitoramento e Diagnóstico da IBM para Java - Analisador de Memória instaladas. O histograma de heap é uma medida simples do número de objetos ativos e da memória usada por classe Java. Infelizmente, dependendo da instalação do Java, as ferramentas necessárias podem não estar disponíveis ou nem sempre funcionar. Para criar um histograma de heap, primeiro é necessário a ID do processo Java. Para obtê-lo, execute o ps or (if available), run:Histograma de Heap
O histograma de heap é uma medida simples do número de objetos ativos e da memória usada por classe Java. Infelizmente, dependendo da instalação do Java, as ferramentas necessárias podem não estar disponíveis ou nem sempre funcionar. Para criar um histograma de heap, primeiro é necessário a ID do processo Java. Para obtê-la, execute ps ou (se disponível), execute:

jps -l

Essa ferramenta Java obtém as IDs do processo de todos os processos Java em execução. Exemplo:

327
3332 sun.tools.jps.Jps
3313 crx-quickstart-....jar

Agora execute o seguinte comando:

jmap -histo 3313

A lista é classificada pela memória total necessária (superficial: excluindo objetos referenciados). As primeiras 20 linhas da saída são as mais interessantes. Exemplo de saída:

JVM version is 1.5.0_20-141
Iterating over heap. This may take a while...
Warning: skipping invalid TLAB for thread t@62211
Warning: skipping invalid TLAB for thread t@62467
...
SizeCountClass description
-------------------------------------------------------
1059290412916byte`[` `]`
1028584075255* ConstMethodKlass
628317658388char`[` `]`
604230414928int`[` `]`
4995752116201* SymbolKlass
422089675255* MethodKlass
41965126969* ConstantPoolKlass
29285606969* InstanceKlassKlass
26310086066* ConstantPoolCacheKlass
2395872149742org.apache.jackrabbit.core.query.lucene.DocId$PlainDocId
14760087003java.util.HashMap$Entry`[` `]`
139612858172java.lang.String
107023244593java.util.HashMap$Entry
75398410036short`[` `]`
73546454org.apache.jackrabbit.core.query.lucene.DocId`[` `]`
7201927502java.lang.Class
64070413348com.day.crx.persistence.tar.index.IndexEntry
...

Informações adicionais

Para ajudar a analisar o problema, também precisamos saber as seguintes informações:

  • Versão do CRX ou CQ, incluindo uma lista de todos os números de versão de hotfixes instalados.
  • Sistema operacional, fornecedor de JVM e versão.

Referências

[ 1] Guia de Solução de Problemas da Central de Ajuda do Oracle > para a VM HotSpot
[ 2]  Oracle.com > javas > DebuggingOptions

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f