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.

Causa

Tais 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. CRX ou CQ precisam de pelo menos 256 MB de heap alocados para serem executados. Se esse for o problema, inicie a partir da linha de comando, verifique se as configurações da memória heap estão definidas. Exemplo:

java -Xmx512m -jar *.jar

Se esse não for o caso, seu aplicativo pode estar retendo muitos objetos sem liberá-los para o Garbage Collection. Isso é chamado de vazamento de memória, veja aqui para maiores informações. Veja a seção abaixo sobre como analisar problemas de memória em aplicativos java.

Análise, solução

Criar um 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 pilha é suficiente para analisar o problema.

Observação: se você estiver usando o script crx-quickstart/server/start para iniciar sua instância CRX, então você pode adicionar -XX: HeapDumpOnOutOfMemoryError à variável CQ_JVM_OPTS (certifique-se de que a variável também não esteja 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á configurada. Execute ps -ef | grep java a partir da linha de comando. Então verifique se você vê -XX:+HeapDumpOnOutOfMemoryError como um parâmetro do processo java CRX.

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

Veja aqui para uma referência de parâmetros jvm relacionados a 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 home do 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 e então vá para Visualizar => Selecione Colunas => PID (Identificador de Processo) ou jps -l
  2. Execute o comando jmap abaixo, substitua /path/to/generate/heapdumpfile.hprof pelo local onde você gostaria de gerar o arquivo de despejo de heap e substitua 1234 com o pid que você procurou 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 ao sinal do usuário. Existem vários tipos de despejos, mas você geralmente precisa do pleno despejo do sistema para realizar uma análise completa da memória. Adicione os seguintes argumentos:

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

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

Para obter mais informações, consulte o guia de ajuda 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. Certifique-se de ter espaço em disco suficiente alocado para o diretório onde o arquivo de despejo é gerado.

Analise o despejo de heap

Uma boa ferramenta para analisar dumps de heap é o EclipseMAT (Eclipse Memory Analyzer): http://www.eclipse.org/mat/

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

Para uma análise completa do dump do sistema, use o Workbench do Assistente de Suporte 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 você precisa do ID do processo Java. Para obtê-lo, execute ps ou (se disponível), execute:

jps -l

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

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

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:

A versão da JVM é 1.5.0_20-141 iterando sobre o heap. Isso pode demorar um pouco ... Aviso: ignorando TLAB inválida para encadeamento t@62211 Aviso: ignorando TLAB inválida para encadeamento t@62467 ... Contagem de tamanhos Descrição da classe --------------- ---------------------------------------- 10592904 12916 byte[] 10285840 75255 * ConstMethodKlass 6283176 58388 char[] 6042304 14928 int[] 4995752 116201 * SymbolKlass 4220896 75255 * MethodKlass 4196512 6969 * ConstantPoolKlass 2928560 6969 * InstanceKlassKlass 2631008 6066 * ConstantPoolCacheKlass 2395872 149742 org.apache.jackrabbit.core.query.lucene.DocId$PlainDocId 1476008 7003 java.util.HashMap$Entry[] 1396128 58172 java.lang.String 1070232 44593 java.util.HashMap$Entry 753984 10036 short[] 735464 54 org.apache.jackrabbit.core.query.lucene.DocId[] 720192 7502 java.lang.Class 640704 13348 com.day.crx.persistence.tar.index.IndexEntry ...

Informações adicionais

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

  • Versões CRX ou CQ, incluindo uma listagem de todos os números de versão de hot fix instalados.
  • Sistema operacional, fornecedor de JVM e versão.

Referências

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

Esta obra está licenciada sob uma licença não adaptada da Creative Commons Attribution-Noncommercial-Share Alike 3.0  As publicações do Twitter™ e do Facebook não são cobertas pelos termos do Creative Commons.

Avisos legais   |   Política de privacidade online