Analisar problemas de memória

Descrição

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

Causa

Esses problemas podem ter muitas causas.

Uma causa possível é 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 ficar 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 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.

Clique 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 o pid do processo java para o 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 em seguida, vá para Exibir = Selecionar colunas = 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.

    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 sua configuração de parâmetro max 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 é EclipseMAT (Eclipse Memory Analyzer): http://www.eclipse.org/mat/

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 Ferramentas de Monitoramento e Diagnóstico da IBM para Java - Memory Analyzer Versão 1.2 instalado no topo.

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 o 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

http://java.sun.com/javase/6/webnotes/trouble/TSG-VM/html/memleaks.html
http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#DebuggingOptions

Nesta página