
Eu tenho duas instâncias diferentes do Tomcat 7 em dois servidores diferentes (oracle jdk7) com configuração de hardware quase igual (ambas > 24 GB de RAM). Ambos os servidores Tomcat têm a mesma configuração e os mesmos aplicativos da web são implantados nesses servidores. As opções de catalina são as seguintes:
-XX:PermSize=128m -XX:MaxPermSize=512M -Xmx2048m -XX:+CMSIncrementalMode -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC
Ao executar um teste de carga (sobrecarregando uma API REST com solicitações pesadas executadas em paralelo), um dos servidores lança java.lang.OutOfMemoryError: Java heap space
(aqui está o stacktrace:http://pastebin.com/wuS1MVCC), o outro servidor funciona perfeitamente. Não tenho ideia de por que isso está acontecendo. Alguém já enfrentou um problema semelhante?
Responder1
Então, o que está acontecendo é que uma de suas JVMs do Tomcat está tentando exceder o heap de 2.048 MB que você alocou para ela.
Parece que você está procurando uma resposta específica tanto quanto uma lista de verificação de coisas para tentar, então aqui está:
A falta de heap ocorre devido a um vazamento de memória, onde você vaza um pouco a cada solicitação, ou em um cenário de carregamento, pode ser porque você está apenas jogando mais na JVM do que ela pode suportar. Você deseja identificar qual deles é o problema, então comece observando como você gera sua carga.
Se o problema ocorrer apenas em um nível alto de solicitações paralelas, mas nunca em um nível inferior, você terá o problema de que o número de solicitações multiplicado pela memória necessária para processar cada solicitação é muito grande. Você precisa fazer com que cada solicitação use menos memória ou limitar a simultaneidade de alguma forma.
Se o problema ocorrer após um determinado número de solicitações ter sido processado, independentemente da simultaneidade, há um vazamento de memória. Você precisa encontrá-lo e recuperar a memória.
Em qualquer cenário, você será muito auxiliado por ter um bom analisador de memória heap. Existem bons comerciais, como YourKit Java Profiler, ou gratuitos, como Eclipse Memory Analyzer. Encontre uma ferramenta que funcione para você e aprenda como usá-la para ver o que está ocupando memória. Observe que você não precisa necessariamente usar a ferramenta para iniciar seu programa - se estiver executando um teste de carga em um servidor, você poderá usar a ferramenta de linha de comando jmap do JDK para capturar um heap dump em um arquivo, e então use sua ferramenta para analisar o arquivo de despejo. A ferramenta mostrará quais objetos estão ocupando espaço na sua pilha.
Responder2
Háalgodiferente entre os dois sistemas, caso contrário o comportamento não seria diferente. Observe que muito tempo gasto no GC com poucos resultados também pode causar o erro. Correr perto dos limites do heap faz com que o GC tenha esse tipo de problema.
Tempo excessivo de GC e OutOfMemoryError
O coletor simultâneo lançará um OutOfMemoryError se muito tempo estiver sendo gasto na coleta de lixo: se mais de 98% do tempo total for gasto na coleta de lixo e menos de 2% do heap for recuperado, um OutOfMemoryError será lançado. Esse recurso foi projetado para evitar que os aplicativos sejam executados por um longo período de tempo e tenham pouco ou nenhum progresso porque o heap é muito pequeno. Se necessário, este recurso pode ser desabilitado adicionando a opção -XX:-UseGCOverheadLimit à linha de comando.