O que causa o PermGen OutOfMemoryError no JBoss?

8

Qual é a causa subjacente de um PermGen OutOfMemoryError no JBoss?

Estou executando o JBoss AS 4.2.2 no meu ambiente de desenvolvimento, e isso ocorre após a reimplantação do meu aplicativo da Web várias vezes.

O blog de Christian Vest Hansen oferece opções de JVM que ajudam muito , mas não resolvem o problema completamente:

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m
Peter Hilton
fonte

Respostas:

5

Como já mencionado, você provavelmente está enfrentando vazamentos nos carregadores de classes. Por algum motivo, suas aulas não estão sendo descarregadas. Isso pode acontecer por duas razões

  • Os objetos dessas classes ainda existem na pilha, os objetos sempre referenciam sua classe ou
  • O carregador de classes é referenciado em algum lugar, por qualquer motivo, os carregadores de classes referenciam suas classes para não carregá-las duas vezes

Não existe uma solução abrangente para esse problema. Uma ferramenta útil para ajudá-lo a encontrar a causa raiz é a Eclipse Memory Analyzer Tool , que você pode aplicar a um dump de heap da sua JVM (você pode ativar dumps de heap em OOMs com a opção -XX: + HeapDumpOnOutOfMemoryError). Talvez comece a procurar objetos java.lang.Class no seu aplicativo da web para ver por que eles estão sendo mantidos vivos. Infelizmente, o PermGen normalmente não faz parte de um dump de heap da JVM, portanto, você só pode tentar encontrar artefatos correlatos no restante do heap (objetos de classe não são armazenados no PermGen se não estiver enganado, apenas o código de byte real é, por favor me corrija se eu estiver errado).

HTH.

Edit:
Dave Cheney sugere em um comentário que java.lang.Class-objects são realmente parte do PermGen e não estão incluídos em um despejo de heap de hotspot normal. A menos que você tenha uma JVM que grave essas informações no dump de heap, precisará de uma abordagem diferente. Você ainda pode procurar instâncias de seus objetos, mas se estiver vazando classes / carregadores de classes (ambos infelizmente se implicam), parece que você precisa procurar outros sinais (objetos de metadados do JBoss, etc.).

falstro
fonte
11
Tenho certeza de que os objetos de classe são armazenados no PermGen (ou seja, objetos que são instâncias de classe). Há uma área separada na Sun JVM chamada Cache de Código, onde é armazenado o código que foi compilado no código da máquina. Tanto o PermGen eo cache de código fazem parte da memória não Heap que você pode ver usando ferramentas como jconsole
Dave Cheney
@ Dave Cheney: Você está correto. Os objetos Class vazados presos no PermGen geralmente são a causa do problema do OP.
Eddie
por enquanto, embora eu não ache que o conteúdo do PermGen esteja gravado no heap dump (isso está usando a Sun JVM, não tenho muita experiência com os outros), o formato hprof dump certamente sabe coisas como classes foram carregadas, quantos carregadores de classe etc. Você pode ver isso ao abrir o hprof no Eclipse Memory Analyzer). O que provavelmente não está gravado são os grandes dados da classe binária que compõem o código de java byte, o que você vê no despejo de heap é o 'stub' da instância de Class armazenada no PermGen.
Dave Cheney
2

A causa subjacente são as referências às classes que foram descartadas vazando fora do carregador de classes, impedindo a JVM de descarregar essas classes do perm perm. Esses sinalizadores usados ​​podem fazer com que a JVM limpe agressivamente classes que não podem ser carregadas, mas não resolverá o problema subjacente.

Há uma explicação boa e complexa aqui

Dave Cheney
fonte
1

A causa do erro PermGen OutOfMemory é que o aplicativo é reimplementado. A causa subjacente é o vazamento de objetos de classe no PermGen das reimplementações.

Obviamente, a solução alternativa é reiniciar a JVM após um certo número de reimplementações.

Esse é um problema muito difícil de resolver totalmente, embora com algumas investigações você possa fazer grandes melhorias. Aqui é onde você começa: Quando o aplicativo da Web for interrompido, verifique se:

  • todos os Threads que você iniciou são parados
  • todos os ThreadPools que você iniciou são desligados
  • todas as referências estáticas que você pode liberar são liberadas

Estas são algumas das coisas que podem fazer com que um objeto Class fique preso no PermGen.

Além disso, observe que nem todas as JVMs (ou todas as versões das JVMs) terão objetos da classe GC no PermGen. Se você estiver executando uma JVM ou uma versão de uma JVM que não terá objetos da Classe GC no PermGen, sua única opção será reiniciar a JVM após um certo número de reimplementações. Isso provavelmente não se aplica a você, dadas as opções de JVM que você menciona.

Eddie
fonte