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.
Oops. O código está pela metade por causa do “<“.
Corrigido. Valeu. ;-)
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!
Legal, Gilmatryx. Espero escrever mais sobre o gerencimento de memória da JVM nos próximos posts. É um assunto vasto e interessante.
Cara… onde que altero esse -XX:?????
onde devo colocar esse parametro??
valeu
no arquivo eclipse.txt que fica na mesma pasta do eclipse.exe no seu diretório padrão de instalação.
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
Olá Leonardo… provavelmente o parâmetro abaixo seja a solução (ou ampliá-lo)
-XX:MaxPermSize=512M
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:(…) “
@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!
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?
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. ;-)
Post de 2007 mas que me ajudou a resolver o meu problema. Valeu pelo post.
Parabens pelo post. Salvando vidas! :D
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.
como que eu coloca esse codigos