BlogNotFoundException

Java, Linux, Open Source, etc...


java.lang.OutOfMemoryError: PermGen space

Continuo em busca de uma solução para esse memory leak. Memory leak em java pode ser causado por um objeto que não é coletado depois que não é mais necessário ou não está mais ativo. Com isso, a performance do computador é prejudicada, pois há uma redução na quantidade de memória disponível.

Ao ler os posts atualizados do Bloglines me deparei com o seguinte post: debugging PermGen OutOfMemoryError problems in windows

Nesse post o autor Rich Unger dá dicas de como debugar esse tipo de bug que é tão difícil de reproduzir. No post, o autor faz referência ao seguinte post do autor Gregg Sporar, que define os diferentes tipos de memory leaks que podem ocorrem em aplicações Java.

http://weblogs.java.net/blog/gsporar/archive/2006/09/javazone_sessio.html

Entre os três tipos, o que mais me interessa no momento é o: Repeatedly deploying my application to Tomcat causes it to run out of perm gen space - is there a problem with perm gen usage in Tomcat.

Parece que o TomCat possui esses problemas de perm gen mesmo, inclusive existe um cadastro de bug no bugzilla do TomCat 5: http://issues.apache.org/bugzilla/show_bug.cgi?id=33711

Para saber melhor onde pode estar ocorrendo o vazamento de memória, o autor indica a utilização do JConsole. O JConsole é uma ferramenta que utiliza instrumentação JMX para prover informações sobre performance e consumo de recursos de aplicações que rodam na plataforma Java.

Iniciando o JConsole
O JConsole pode ser encontrado em JAVA_HOME/bin, onde JAVA_HOME é o diretório onde o JDK foi instalado. O JConsole pode ser utilizado tanto para monitoramento de aplicações locais quanto aplicações remotas.

Monitoramento e Gerenciamento Local
Para habilitar o acesso local ao JMX, precisamos criar a seguinte propriedade quanto iniciarmos a JMV ou aplicação Java:
com.sun.management.jmxremote
Por exemplo, para utilizarmos o JConsole com o TomCat devemos executar os seguintes comandos na linha de comando:
TOMCAT_HOME\bin> set JAVA_OPTS=-Dcom.sun.management.jmxremote
TOMCAT_HOME\bin> catalina start
Após executar os comandos acima, inicie o JConsole e note que há uma configuração na aba Local apontando para a classe: org.apache.catalina.startup.BootStrap. Isso indica que o JConsole já pode monitorar o TomCat. Em seguida cliquem em Connect.

A Interface do JConsole
A interface do JConsole é composta por seis abas:

* Summary tab: exibe informações sobre a JVM e valores monitorados.
* Memory tab: exibe informações sobre o uso de memória.
* Threads tab: exibe informações sobre o uso de threads.
* Classes tab: exibe informações sobre o carregamento das classes.
* MBeans tab: exibe informações sobre MBeans.
* VM tab: exibe informações sobre a JVM.



Na aba Memory, podemos encontrar informações sobre o consumo e pools de memória:



Na aba Classes, podemos encontrar informações sobre o carregamento das classes, incluindo o total de classes carregadas, total de classes não carregadas, etc...



Até agora encontrei as seguintes possíveis soluções para esse problema:

* Utilizar a flag -XX:MaxPermSize para aumentar o tamanho de memória disponível (o default é 64M)

* Migrar para outro WebContainer (Jetty ou Resin)

* Mudar de implemetação de JDK, utilizar por exemplo a JRockit (Algumas pessoas dizem que após a mudança, esse problema não persiste)

Fontes:
http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html
http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html
http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html

7 Responses to “java.lang.OutOfMemoryError: PermGen space”

  1. # Anonymous Anônimo

    Esse é um problema do classloader do tomcat. tem uma issue para corrigir isso no bugtrack  

  2. # Blogger Guilherme

    O link para a issue é: http://issues.apache.org/bugzilla/show_bug.cgi?id=40679  

  3. # Anonymous Anônimo

    Olha, ....

    Na verdade tive o seguinte problema:

    Na JRockit vc recebe um DUMP do tamanho do mundo com todas as informações baixo nível e a seguinte mensagem de erro:

    Error Message: Illegal memory access. [54]


    Aí mudei para o Mustang e recebi essa:

    java.lang.OutOfMemoryError: PermGen space.

    Pois é, o problema é o da JVM mesmo.
    Dependendo da Aplicação vc deve usar a option de comando para aumentar a Perm Generation.  

  4. # Anonymous Anônimo

    Acho muito exagero a troca de conteiner , ainda mais reviver um que ja morreu a anos o resin.. E trocar de JVM,,a fala serio amigo...

    La no banco do brasil a gente coloca 512 o permgem pq nao tem uma "solucao" é pouco divulgado pela sun...  

  5. # Anonymous Anônimo

    Ola Galera... eu enfrento esse problema de PermGen a muito tempo.. e nao so no tomcat...
    Sou arquiteto de Software especializado em Java.. e geralmente trabalho com aplicacoes de Grande porte..
    Ja tive esse problemas em aplicacoes sobre Weblogic com heapsize de 5Gb .. e 1Gb de Perm size...
    Esse problema acontece qdo vc usa eclipse... qdo vc usa ate mesmo o iReports...
    Eu acredito q o problema nao esta nessas aplicacoes.. e sim no exagero.. do uso de alguns recursos..
    Vamos analizar o problema...
    Primeiro ponto, na minha opnião PermGen outOfMemory errors nao sao MemoryLicks..
    O nome PermGen Space ja diz : "Espaço Permanente..."
    O Perm é um espaço de memória da VM utilizado para o carregamento das classes/bytecode e é fixo .. o Garbage collector não atua sobre essa área.. ele nao limpa objetos ali... então não é um memorylick.. e sim um problema de DIMENSIONAMENTO...

    Agora... se é um espaço fixo.. usado para o carregamento do bytecode.. esses erros deveriam ocorrer no startup das aplicacoes.. onde se supõe q o bytecode é carregado.. e nao no decorrer do tempo...

    Na verdade.. nao é no startup q todo o bytecode é carregado..
    Pela natureza dinâmica de Java.. muitas classes podem ser carregadas on-the-fly usando um Class.forName("..") por exemplo...

    Agora na minha opnião... o Grande vilão... q vem causando a maioria dos erros de PermGen são aplicações q utilizando a geracao de byteCode em runtime .. como javasist (do JBoss), CGLIB (usado pelo hibernate e Spring) e a propria criacao de proxys pela VM...

    Imagina o seguinte fluxo de vida para uma aplicacao Spring + Hibernate...
    Qdo vc da o deploy a primeira vez.. e comeca a utilizar.. o container carrega as classes.. REAIS.. da sua aplicacao e de suas dependencias..
    qdo vc comeca a utilizar a aplicacao o Spring vai criar algumas classes em runtime.. para ser os proxys.. de aspecto da sua aplicacao para controlar transacao etc...
    o Hibernate tb vai criar classes proxy para suas entidades.. para fazer lazyLoading.. etc..
    qdo vc da re-deploy de uma aplicacao dessas ... a session factory do hibernate e a beanFactory do Spring.. ja nao vao conhecer as classes geradas anteriormente.. e vao gerar novamente todas estas classes/proxys novamente.. e isso vai enchendo o PermGen Space... e como eu disse antes o Garbage Collector NUNCA limpa este espaço.

    Para concluir ... na minha opniao o problema HOJE é de dimensionamento.. vc deve entender se sua aplicacao gera bytecode em runtime.. e saber q ela vai exigir mais PermGen Space ...

    Eu disse o problema HOJE .. por q é assim q as VMs se comportam.. talvez no futuro esse problema nao ocorra... com uma implementacao mais inteligente do PermGen Space.. talvez..  

  6. # Blogger Seiti

    Bem elucidativo este último comentário, mas, memorylick? =)  

  7. # Anonymous João Junior

    Tambem estou tendo este problema.

    Na verdade o GC passa no PermGen, mas usando o Metodo MarkAndSweep, e como 99% das Classes no PermGen são necessarias e nao foram marcadas como lixo, o PermGen cresçe desse jeito.  

Postar um comentário