Palavras-chave: java, permgen, falta de memória, geração permanente

A máquina virtual Java tem uma área de memória limitada chamada Geração Permanente (Perm Generation), onde são armazenados objetos cuja desalocação é rara (ex.: código de classes, objetos de reflexão, pool de strings etc). Dado que esta área de memória é limitada, seu uso intenso pode gerar erros com a seguinte mensagem:

java.lang.OutOfMemoryError: PermGen space

Como a mensagem diz, isto acontece porque não há mais espaço na memória reservada para a Geração Permanente. Para que este problema não aconteça mais, use a opção -XX:MaxPermSize na inicialização da JVM. Isso aumentará o tamanho máximo da memória de Geração Permanente, como no exemplo a seguir:

java -XX:MaxPermSize=128m pacote.MinhaClasse

Neste caso, configuramos o tamanho máximo da memória de geração permanente para 128 megabytes, sendo que o tamanho padrão é 64 megabytes.

Uma demonstração pode ser feita com o código a seguir:

public class TestePerm {
   public static void main(String[] args) {
      int numeroDeAlocacoes = 0;
      try {
         System.out.println("Alocando...");
         ArrayList list = new ArrayList();
         String grandeString = new
            BigDecimal(1000).pow(1000).toString();
         for (int i = 0; i < 1000000; i++)
            list.add((grandeString + numeroDeAlocacoes++).intern());
         System.out.println("Fim.");
      } catch (OutOfMemoryError e) {
         System.out.println(e);
         System.out.println("Alocacoes antes do erro: " + numeroDeAlocacoes);
      }
   }
}

Este programa usa o método intern() da classe String para alocar strings no pool da JVM e fazer estourar a memória de geração permanente.

A seguir, vemos dois exemplos de execuções do programa TestePerm:

$ java codare.TestePerm
Alocando...
java.lang.OutOfMemoryError: PermGen space
Alocacoes antes do erro: 11087
$ java -XX:MaxPermSize=128m codare.TestePerm
Alocando...
java.lang.OutOfMemoryError: PermGen space
Alocacoes antes do erro: 22183

Na primeira execução, com o MaxPermSize configurado para 64 megabytes (tamanho padrão), conseguimos colocar apenas 11087 strings no pool antes de acabar a memória permanente. No segundo caso, com 128 megabytes de MaxPermSize, conseguimos fazer 22183 alocações.

A área de geração permanente é usada intensivamente em servidores de aplicação, pois estes executam milhares de classes e ficam meses no ar. Portanto, em um ambiente de produção, nunca se esqueça de configurar um tamanho máximo adequado para a memória permanente da JVM.