Java: Solucionando o erro de "PermGen space"

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.

This entry was posted in Java. Bookmark the permalink.

17 Responses to Java: Solucionando o erro de "PermGen space"

  1. Oops. O código está pela metade por causa do “<“.

  2. Corrigido. Valeu. ;-)

  3. Gilmatryx says:

    Pô cara…

    Cheguei aqui pelo google Lendo Tudo Sobre OutOfMemoryError (OOME).

    Parabéns, muito abrangente e didático.
    Quem sabe umas referências para o assunto :-)

    Tipo:

    http://www.javaspecialists.co.za/archive/Issue092.html
    http://blognotfoundexception.blogspot.com/2006/10/javalangoutofmemoryerror-permgen-space.html

    E valeu… Tá de parabéns!

  4. Legal, Gilmatryx. Espero escrever mais sobre o gerencimento de memória da JVM nos próximos posts. É um assunto vasto e interessante.

  5. Rodrigo says:

    Cara… onde que altero esse -XX:?????
    onde devo colocar esse parametro??
    valeu

    • Fernando says:

      no arquivo eclipse.txt que fica na mesma pasta do eclipse.exe no seu diretório padrão de instalação.

  6. Leonardo Duval says:

    Olá,

    Achei bem interessante as tuas explicações sobre o erro de Perm Gen, porem ainda enfrento problemas no meu ambiente de produção que se possível gostaria da tua ajuda.
    Tenho o seguinte cenário, Java 1.6, Tomcat 6.0.14 Max memory 2490Mb (por sinal, o máximo que consigo colocar no Linux, mais que isto o Java não starta, se souber como posso ampliar…). Oque ocorre é que de acordo com o uso da aplicação durante o dia ocorre o famoso “Out Of Memory Perm Gen”. Para solucionar este problema, aumentei a memoria física e o min e o max memory do java (JAVA_OPTS) porem quando as aplicações eram muito utilizadas ocorria o problema, se tiveres uma ideia de como posso fazer para solucionar serei muito grato! OBS: O servidor é reiniciado somente o Tomcat e o banco a máquina permanece sempre ligada.

    Desde já obrigado.

    Abraço,

    Leonardo

  7. Glaudiston says:

    Olá Leonardo… provavelmente o parâmetro abaixo seja a solução (ou ampliá-lo)
    -XX:MaxPermSize=512M

  8. thiago says:

    ola,
    tentem isso:

    http://www.jroller.com/agileanswers/entry/preventing_java_s_java_lang

    tem uma explicacao interessante no primeiro posto do comentario.

    “I also had these annoying Perm Gen Space OOMs when redeploying webapps. I’m using spring 1.2.8, Hibernate 3 (both with CGLIB 2.1_3), tomcat 5.5.17 and – now the problem: jdk1.5.0_06. After upgrading to jdk1.5.0_07 my Perm Gen Space gets gc’ed like it should be – no increase of Perm Gen Space, no code changes.

    There were however some learnings on the way:(…) “

  9. @Leonardo Duval:

    Indico você fazer uma análise de como está o GC de sua aplicação. Para sua aplicação ‘printar’ informações sobre o GC coloque isso na linha de iniciação de sua aplicação ou no java OPTs: “-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -verbose:gc” Assim você pode fazer uma análise de como está o consumo de memória de sua maquina! Existem tools que auxiliam nessa análise, veja um pouco sobre o visualVM. Alé de não utilizar o valor default do PermGen que é 64. Tente utilizar ” -XX:PermSize=256M -XX:MaxPermSize=512M ” Veja também qual é o SO que está rodando sua aplicação, lembrando do limite q os S.O’s 32bits te impõem. Com muita frequencia posto coisas em meu blog sobre performance, rafacastanho.wordpress.com abraço!

  10. Marco Antonio Mendonça says:

    Estou utilizando o eclipse galileo e oc4j. E nao consigo subir duas aplicacoes, pois da erro de permgem, ja fiz varias alterações no eclipse.ini e não resolveu. Alguem pode me ajudar?

  11. O post é bom, porém o título, não corresponde muito bem a realidade. Não esqueçamos que caso tenhamos um problema de memory leak, estaremos apenas retardando o problema, e não solucionando.

    Abraços.

    • Obrigado pelo comentário, Alexandre. Acho que, na maioria das vezes, o erro de PermGen space é gerado por uma aplicação que cresceu muito ou uma aplicação empacotada que você está instalando em seu appserver. Nestes casos, você alterará uma vez só o parâmetro e “solucionará” o problema. ;-)

  12. Ícaro Magnago says:

    Post de 2007 mas que me ajudou a resolver o meu problema. Valeu pelo post.

  13. Rafael says:

    Parabens pelo post. Salvando vidas! :D

  14. LucasJohn says:

    Belo post! Porém… Como já dito, vale a pena acrescentar que isso, realmente, não soluciona o problema. Por exemplo, se você remove e adiciona uma aplicação no servidor de aplicação, isso gera um leak de memória. Quando você tem múltiplas aplicações rodando e quer atualizá-las, estará limitado pela PermGen, e aumentando o tamanho dela só retarda o problema. Ainda não encontrei de fato uma solução para a questão.

  15. como que eu coloca esse codigos

Comments are closed.