Compilador JIT Java causando OutOfMemoryError

Um aplicativo que começamos a travar esporadicamente recentemente com uma mensagem sobre "java.lang.OutOfMemoryError: solicitou 8589934608 bytes para Chunk :: new. Sem espaço de troca?".

Eu olhei em volta na rede e em todos os lugares as sugestões são limitadas a

reverter para uma versão anterior do Javamexer com as configurações de memóriause o cliente em vez do modo de servidor

A reversão para uma versão anterior implica que o novo Java tenha um erro, mas não vi nenhuma indicação disso. A memória não é um problema; o servidor tem 32 GB disponíveis e o Xmx é definido como 20 enquanto o Xms é 10. Não consigo ver a JVM esgotando os 12 GB restantes (menos a quantidade atribuída a outros processos na máquina). E estamos presos ao modo de servidor devido à natureza do aplicativo e do ambiente.

Quando olho para o uso da memória e da CPU do aplicativo, vejo o uso constante da memória durante todo o dia, mas de repente, pouco antes de morrer, o uso da CPU sobe para 100% e o uso da memória passa de X para X + 2 GB, para X + 4GB, para (às vezes) X + 8GB, para morte da JVM. Parece que talvez haja um ciclo de redimensionamento repetido da matriz na compilação JIT.

Eu já vi o erro ocorrer com a solicitação de 8 GB acima e também com 16 GB. Sempre, o método que está sendo compilado quando isso acontece é o mesmo. É um método simples que possui loops não aninhados, sem recursão e usa métodos em objetos que retornam campos de membros estáticos ou campos de membros de instância diretamente com pouco cálculo.

Então, eu tenho 2 perguntas:

Alguém tem alguma sugestão?Posso testar se há um problema ao compilar esse método específico em um ambiente de teste, sem executar o aplicativo inteiro, invocando o compilador JIT diretamente? Ou devo iniciar o aplicativo e pedir para ele compilar métodos após uma contagem de chamadas muito menor (como 2) para forçá-lo a compilar o método quase instantaneamente, em vez de em um ponto aleatório do dia?

@StephenC

A JVM é 1.6.0_20 (anteriormente 1.6.0_0), executando no Solaris. Eu sei que é a compilação que está causando um problema por algumas razões.

ps nos segundos que antecedem, mostra que um encadeamento java com o ID correspondente ao encadeamento do compilador (do jstack) está ocupando 100% do tempo da CPUjstack mostra que o problema está emJavaThread "CompilerThread1" daemon [_thread_in_native, id=34, ...]

O método mencionado emjstack é sempre o mesmo, e é o que escrevemos. Se você olhar para a amostrajstack você saberá o que quero dizer, mas, por razões óbvias, não posso fornecer exemplos de código ou nomes de arquivos. Eu direi que é um método muito simples. Essencialmente, um punhado de verificações nulas, 2 para loops que fazem verificações de igualdade e possivelmente atribuem valores, e algum método simples chama depois. Ao todo, talvez 40 linhas de código.

Esse problema ocorreu duas vezes em duas semanas, embora o aplicativo seja executado todos os dias e reiniciado diariamente. Além disso, o aplicativo não estava sob carga pesada em nenhum desses momentos.

questionAnswers(3)

yourAnswerToTheQuestion