Pergunta

Recentemente eu corri para este erro no meu aplicativo web:

java.lang.OutOfMemoryError: espaço PermGen

É uma aplicação / JPA + IceFaces / JSF típica Hibernate em execução no Tomcat 6 e JDK 1.6. Aparentemente, isso pode ocorrer após a reinstalação de um aplicativo algumas vezes.

O que ele faz eo que pode ser feito para evitá-lo? Como faço para corrigir o problema?

Foi útil?

Solução

A solução foi adicionar esses sinalizadores para a linha de comandos da JVM quando o Tomcat é iniciado:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

Você pode fazer isso por desligar o serviço tomcat, em seguida, indo para o diretório Tomcat / bin e executando tomcat6w.exe. Sob a guia "Java", adicione os argumentos para a caixa "Opções Java". Clique em "OK" e reinicie o serviço.

Se você receber um erro o serviço especificado não existe como um serviço instalado você deve executar:

tomcat6w //ES//servicename

que servicename é o nome do servidor como visto em services.msc

Fonte:. O comentário de Orx em de Eric

Outras dicas

É melhor tentar -XX:MaxPermSize=128M em vez de -XX:MaxPermGen=128M.

Eu não posso dizer o uso preciso deste pool de memória, mas tem a ver com o número de classes carregadas no JVM. (Assim, permitindo descarga de classe para tomcat pode resolver o problema). Se os seus aplicativos gera e aulas compila em fuga é mais provável a necessidade de um pool de memória maior do que o padrão.

aplicativo de servidor PermGen erros que acontecem após várias implantações são provavelmente causado por referências mantidas pelo contêiner em classloaders seus velhos Apps. Por exemplo, usando uma classe nível de log personalizado fará referências a ser realizada pelo carregador de classe do servidor de aplicativos. Você pode detectar esses vazamentos inter-classloader utilizando ferramentas de análise modernos (JDK6 +) JVM como jmap e jhat de olhar para que as classes continuam a ser realizada em seu aplicativo, e redesenhar ou eliminar seu uso. suspeitos do costume são bancos de dados, madeireiros e outras bibliotecas-estrutura de nível base.

carregador de classe: o temido "java.lang .OutOfMemoryError: PermGen space" exceção, e especialmente a sua acompanhamento pós .

Os erros mais comuns que as pessoas fazem é pensar que espaço de pilha e espaço PermGen são as mesmas, o que não é de todo verdade. Você pode ter muito espaço restante na pilha, mas ainda pode ficar sem memória em permgen.

As causas mais comuns de OutofMemory em PermGen é ClassLoader. Sempre que uma classe é carregado na JVM, todos os seus dados meta, juntamente com Classloader, é mantido na área PermGen e eles serão lixo recolhido quando o Classloader que eles carregado está pronto para a recolha de lixo. Em caso Classloader tem um vazamento de memória do que todas as classes carregadas por ele permanecerá na memória e causa permgen outofmemory uma vez que você repeti-lo um par de vezes. O exemplo clássico é Java.lang.OutOfMemoryError: PermGen Space in Tomcat .

Agora, existem duas maneiras de resolver isso:
1. Encontrar a causa do vazamento de memória ou se houver qualquer vazamento de memória.
o tamanho 2. Aumento de PermGen Espaço usando JVM -XX:MaxPermSize param e -XX:PermSize.

Você também pode verificar href="http://javarevisited.blogspot.com/2011/09/javalangoutofmemoryerror-permgen-space.html" 2 Solução de Java.lang.OutOfMemoryError em Java para obter mais detalhes.

Use o parâmetro de linha de comando -XX:MaxPermSize=128m para uma Sun JVM (obviamente substituindo 128 para o tamanho que você precisa).

Tente -XX:MaxPermSize=256m e se persistir, tente -XX:MaxPermSize=512m

acrescentou -XX: MaxPermSize = 128m (você pode experimentar o que funciona melhor) para Argumentos VM como eu 'm usando eclipse ide. Na maior parte da JVM, padrão PermSize é de cerca de 64MB que fique sem memória se houver muitas classes ou grande número de cordas no projeto.

Para eclipse, também é descrito em .

PASSO 1 : clique duas vezes no servidor tomcat em Servidores

enter descrição da imagem aqui

PASSO 2 : Abrir lançamento Conf e adicione -XX: MaxPermSize = 128m ao final de argumentos VM existentes .

enter descrição da imagem aqui

Eu estive batendo de minha cabeça contra este problema durante a implantação e undeploying uma aplicação web complexa também, e pensei que eu iria adicionar uma explicação e minha solução.

Quando eu implantar um aplicativo no Apache Tomcat, um novo ClassLoader é criado para esse aplicativo. O ClassLoader é então usado para carregar todas as classes da aplicação, e em undeploy, tudo deveria ir embora bem. No entanto, na realidade não é tão simples.

Uma ou mais das classes criadas durante a vida do aplicativo web contém uma referência estática que, em algum lugar ao longo da linha, as referências a ClassLoader. Como a referência é originalmente estática, nenhuma quantidade de coleta de lixo irá limpar esta referência up -. ClassLoader, e todas as classes Ele é carregado, estão aqui para ficar

E depois de um par de reimplementa, encontramos o OutOfMemoryError.

Agora, isso se tornou um problema bastante grave. Eu poderia ter certeza de que Tomcat é reiniciado após cada redeploy, mas que leva para baixo de todo o servidor, em vez de apenas o aplicativo que está sendo reimplantado, que muitas vezes não é viável.

Então, ao invés eu coloquei uma solução em código, que funciona no Apache Tomcat 6.0. Eu não testei em quaisquer outros servidores de aplicativos, e de salientar que isso é muito provável que não trabalho, sem modificação em qualquer outro servidor de aplicativos .

Eu também gostaria de dizer que, pessoalmente, eu odeio esse código, e que ninguém deve estar usando isso como uma "solução rápida" se o código existente pode ser alterado para usar métodos de encerramento e limpeza apropriada . A única vez que isso deve ser usado é se há uma biblioteca externa seu código é dependente (No meu caso, era um cliente RADIUS) que não fornece um meio para limpar suas referências própria estáticos.

De qualquer forma, com o código. Esta deve ser chamado no ponto onde o aplicativo está undeploying -. Tais como um servlet de destruir método ou (a melhor abordagem) Método contextDestroyed um ServletContextListener

//Get a list of all classes loaded by the current webapp classloader
WebappClassLoader classLoader = (WebappClassLoader) getClass().getClassLoader();
Field classLoaderClassesField = null;
Class clazz = WebappClassLoader.class;
while (classLoaderClassesField == null && clazz != null) {
    try {
        classLoaderClassesField = clazz.getDeclaredField("classes");
    } catch (Exception exception) {
        //do nothing
    }
    clazz = clazz.getSuperclass();
}
classLoaderClassesField.setAccessible(true);

List classes = new ArrayList((Vector)classLoaderClassesField.get(classLoader));

for (Object o : classes) {
    Class c = (Class)o;
    //Make sure you identify only the packages that are holding references to the classloader.
    //Allowing this code to clear all static references will result in all sorts
    //of horrible things (like java segfaulting).
    if (c.getName().startsWith("com.whatever")) {
        //Kill any static references within all these classes.
        for (Field f : c.getDeclaredFields()) {
            if (Modifier.isStatic(f.getModifiers())
                    && !Modifier.isFinal(f.getModifiers())
                    && !f.getType().isPrimitive()) {
                try {
                    f.setAccessible(true);
                    f.set(null, null);
                } catch (Exception exception) {
                    //Log the exception
                }
            }
        }
    }
}

classes.clear();

Como alternativa, você pode alternar para JRockit que manipulação permgen diferente, então JVM do sol. Ele geralmente tem melhor desempenho também.

http://www.oracle.com/technetwork/middleware/ JRockit / overview / index.html

1) aumentar o tamanho PermGen memória

A primeira coisa que se pode fazer é fazer com que o tamanho do espaço de pilha geração permanente maior. Isso não pode ser feito com os -Xms habituais (definir tamanho de heap inicial) e -Xmx (set tamanho máximo de heap) argumentos JVM, uma vez que, como mencionado, o espaço permanente geração de pilha é totalmente separado do espaço regular Java Heap, e esses argumentos definir o espaço para este espaço regular heap Java. No entanto, existem argumentos semelhantes que podem ser usadas (pelo menos com o sol / OpenJDK JVMs) para fazer o tamanho da pilha de geração permanente maior:

 -XX:MaxPermSize=128m

O padrão é 64m.

2) Habilitar Varrendo

Outra maneira de cuidar disso para o bem é permitir que as classes para ser descarregado para que o seu PermGen nunca se esgota:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

Coisas como essa magia funcionou para mim no passado. Uma coisa, porém, há um comércio significativo desempenho off em usar aqueles, já que varre PermGen vai fazer como um extra de 2 pedidos de cada pedido que você fizer ou algo nesse sentido. Você precisa equilibrar o seu uso com as compensações.

Você pode encontrar os detalhes deste erro.

http://faisalbhagat.blogspot.com/2014/09/ java-OutOfMemoryError-permgen.html

A mensagem espaço java.lang.OutOfMemoryError: PermGen indica que a área de Geração Permanente na memória está esgotado.

Os aplicativos Java é permitido usar uma quantidade limitada de memória. A quantidade exata de memória que o uso do aplicativo lata particular é especificado durante a inicialização do aplicativo.

memória Java é separado em diferentes regiões que podem ser vistos na imagem a seguir:

enter descrição da imagem aqui

Metaspace: Um novo espaço de memória nasce

O JDK 8 HotSpot JVM agora está usando memória nativa para a representação de metadados classe e é chamado Metaspace; semelhante ao do Oracle JRockit e IBM JVM.

A boa notícia é que isso significa que há mais problemas de espaço java.lang.OutOfMemoryError: PermGen e não há necessidade para que você possa ajustar e monitorar este espaço de memória mais usando Java_8_Download ou superior.

Eu tive o problema que estamos falando aqui, meu cenário é eclipse-Helios + tomcat + jsf e que você estava fazendo está fazendo um implantar um aplicativo simples de tomcat. Eu estava mostrando o mesmo problema aqui, resolvido da seguinte forma.

Em eclipse vá para servidores clique duas vezes no servidor registrado no meu caso tomcat 7.0, ele abre o meu servidor de arquivos informações de registro geral. Na seção "Informação Geral" clique no link "configuração de lançamento Open" , isso abre a execução de opções do servidor na guia Argumentos na argumentos VM adicionado no final estes duas entradas

-XX: MaxPermSize = 512m
-XX: PermSize = 512m

e pronto.

A resposta mais simples nos dias de hoje é usar Java 8.

Não é mais memória reservas exclusivamente para o espaço PermGen, permitindo que a memória PermGen a co-se misturam com o pool de memória regular.

Tenha em mente que você terá que remover todos os parâmetros -XXPermGen...=... não-padrão JVM inicialização se você não quer Java 8 a reclamar que eles não fazem nada.

  1. Open tomcat7w do diretório bin do Tomcat ou tipo de monitor Tomcat no menu Iniciar (Uma janela com guias abre com várias informações de serviço).
  2. Na área de texto Opções Java acrescentar esta linha:

    -XX:MaxPermSize=128m
    
  3. Set pool de memória inicial para 1024 (opcional).
  4. Piscina Memória Set máxima para 1024 (opcional).
  5. Clique em OK.
  6. Reinicie o serviço Tomcat.

Perm gen erro de espaço ocorre devido ao uso amplo espaço em vez de JVM fornecido espaço para executar o código. A melhor solução para este problema em sistemas operacionais UNIX é mudar alguma configuração em arquivo bash. Seguintes passos resolver o problema.

Executar gedit .bashrc comando no terminal.

Criar variável JAVA_OTPS com seguinte valor:

export JAVA_OPTS="-XX:PermSize=256m -XX:MaxPermSize=512m"

Salve o arquivo bash. Execute o bash exec comando no terminal. Reinicie o servidor.

Espero que esta abordagem irá funcionar no seu problema. Se você usar uma versão Java inferior a 8 esse problema ocorre às vezes. Mas se você usar Java 8 o problema nunca ocorre.

O aumento de tamanho ou GC ajustes parâmetros de geração permanente não vai ajudar se você tem um vazamento de memória real. Se o seu aplicativo ou alguma biblioteca parte 3 que ele usa, carregadores de vazamentos de classe a única solução real e permanente é encontrar esse vazamento e corrigi-lo. Há um número de ferramentas que podem ajudá-lo, um dos recente é Plumbr , que acaba de lançar uma nova versão com o necessário capacidades.

Além disso, se você estiver usando o log4j em sua webapp, verifique este parágrafo em log4j documentação .

Parece que se você estiver usando PropertyConfigurator.configureAndWatch("log4j.properties"), você causar vazamentos de memória quando você undeploy seu webapp.

Eu tenho uma combinação de Hibernate + Eclipse RCP, tentei usar -XX:MaxPermSize=512m e -XX:PermSize=512m e parece estar a trabalhar para mim.

-XX:PermSize=64m -XX:MaxPermSize=128m Set. Mais tarde, você também pode tentar aumentar MaxPermSize. Espero que ele vai trabalhar. O mesmo funciona para mim. Definição só MaxPermSize não funcionou para mim.

Eu tentei várias respostas ea única coisa que finalmente fez o trabalho era esta configuração para o plugin compilador no pom:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <fork>true</fork>
        <meminitial>128m</meminitial>
        <maxmem>512m</maxmem>
        <source>1.6</source>
        <target>1.6</target>
        <!-- prevent PermGen space out of memory exception -->
        <!-- <argLine>-Xmx512m -XX:MaxPermSize=512m</argLine> -->
    </configuration>
</plugin>

Esperamos que esta ajuda.

resolvido isso para mim também; No entanto, notei que os tempos servlet reinício eram muito piores, por isso, enquanto era melhor na produção, que era uma espécie de arrasto em desenvolvimento.

A configuração da memória depende da natureza do seu aplicativo.

O que você está fazendo?

O que é a quantidade de transações precessed?

Como a quantidade de dados que você está carregamento?

etc.

etc.

etc

Provavelmente você poderia perfil de seu aplicativo e começar a limpar alguns módulos do seu aplicativo.

Aparentemente, isso pode ocorrer após a reinstalação de um aplicativo algumas vezes

Tomcat tem implantar quente, mas consome memória. Tente reiniciar o recipiente de vez em quando. Além disso, você precisará saber a quantidade de memória necessária para executar no modo de produção, isso parece um bom momento para que a pesquisa.

Eles dizem que a última rev de Tomcat (6.0.28 ou 6.0.29) lida com a tarefa de servlets reimplantação muito melhor.

eu me deparo com exatamente o mesmo problema, mas infelizmente nenhuma das soluções sugeridas realmente funcionou para mim. O problema não aconteceu durante a implantação, e eu não era nem fazendo qualquer implantações quentes.

No meu caso o problema ocorreu sempre no mesmo ponto durante a execução do meu web-application, ao conectar (via hibernate) ao banco de dados.

Este link (também mencionado anteriormente) forneceu interior suficientes para resolver o problema. Movendo o jdbc- (mysql) -Driver fora do WEB-INF e para o jre / / / pasta lib ext parece ter resolvido o problema. Esta não é a solução ideal, uma vez que a atualização para um JRE mais recente seria necessário que você reinstalar o driver. Outro candidato que poderia causar problemas semelhantes é log4j, então você pode querer mover que um bem

O primeiro passo em tal caso é verificar se o GC é permitido às aulas descarregamento de PermGen. O JVM padrão é bastante conservadora a este respeito - aulas nascemos para viver para sempre. Assim, uma vez carregado, aulas de permanecer na memória mesmo se nenhum código é usá-los mais. Isso pode se tornar um problema quando o aplicativo cria um monte de aulas de forma dinâmica e as classes geradas não são necessários para períodos mais longos. Em tal caso, permitindo que a JVM para definições de classe de descarregamento pode ser útil. Isto pode ser conseguido através da adição de parâmetro apenas uma configuração para seus scripts de inicialização:

-XX:+CMSClassUnloadingEnabled

Por padrão, esta é definida como false e, assim, permitir que isso, você precisa definir explicitamente a opção a seguir em opções de Java. Se você ativar CMSClassUnloadingEnabled, GC varrerá PermGen também e remover classes que não são mais usados. Tenha em mente que esta opção irá funcionar apenas quando UseConcMarkSweepGC também é habilitado usando o abaixo opção. Assim, quando em execução ParallelGC ou, Deus me livre, GC Serial, certifique-se de ter definido o seu GC para CMS, especificando:

-XX:+UseConcMarkSweepGC

Atribuindo Tomcat mais memória não é a solução adequada.

A solução correcta é fazer uma limpeza após o contexto é destruída e recriados (a implantar quente). A solução é parar os vazamentos de memória.

Se o seu Tomcat / Webapp servidor está lhe dizendo que não conseguiu motoristas Unregister (JDBC), em seguida, cancelar o registro deles. Isto irá parar os vazamentos de memória.

Você pode criar um ServletContextListener e configurá-lo no seu web.xml. Aqui está uma ServletContextListener amostra:

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.log4j.Logger;

import com.mysql.jdbc.AbandonedConnectionCleanupThread;

/**
 * 
 * @author alejandro.tkachuk / calculistik.com
 *
 */
public class AppContextListener implements ServletContextListener {

    private static final Logger logger = Logger.getLogger(AppContextListener.class);

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        logger.info("AppContextListener started");
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        logger.info("AppContextListener destroyed");

        // manually unregister the JDBC drivers
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                logger.info(String.format("Unregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                logger.info(String.format("Error unregistering driver %s", driver), e);
            }

        }

        // manually shutdown clean up threads
        try {
            AbandonedConnectionCleanupThread.shutdown();
            logger.info("Shutting down AbandonedConnectionCleanupThread");
        } catch (InterruptedException e) {
            logger.warn("SEVERE problem shutting down AbandonedConnectionCleanupThread: ", e);
            e.printStackTrace();
        }        
    }
}

E aqui você configurá-lo no seu web.xml:

<listener>
    <listener-class>
        com.calculistik.mediweb.context.AppContextListener 
    </listener-class>
</listener>  

"Eles" estão errados, porque eu estou correndo 6.0.29 e têm o mesmo problema, mesmo depois de definir todas as opções. Como Tim Howland disse acima, estas opções só adiar o inevitável. Eles permitem-me para reimplantar 3 vezes antes de bater o erro em vez de cada redeploy vez que eu.

Você está recebendo esta no IDE eclipse, mesmo depois de definir os parâmetros --launcher.XXMaxPermSize, -XX:MaxPermSize, etc, ainda se você está recebendo o mesmo erro, é mais provável é que o eclipse está usando uma versão de buggy do JRE que teria sido instalado por alguns aplicativos de terceiros e definir a padrão. Estas versões de buggy não pegar os parâmetros PermSize e assim não importa o que você definir, você ainda continuo recebendo esses erros de memória. Assim, em seus eclipse.ini adicionar os seguintes parâmetros:

-vm <path to the right JRE directory>/<name of javaw executable>

Certifique-se também definir o JRE padrão nas preferências do eclipse para a versão correta do java.

A única maneira que funcionou para mim foi com o JRockit JVM. Eu tenho MyEclipse 8.6.

lojas de pilha da JVM todos os objetos gerados por um programa Java em execução. Java usa o operador new para criar objetos e memória para novos objetos é alocado na pilha em tempo de execução. A coleta de lixo é o mecanismo de libertar automaticamente a memória contidas pelos objetos que não são mais referenciados pelo programa.

Eu estava tendo problema semelhante. O meu é JDK 7 + Maven 3.0.2 + Struts 2.0 + Google Guice projeto baseado injeção de dependência.

Sempre que eu tentei correr mvn clean package comando, ele estava mostrando seguinte erro e "FALHA BUILD" ocorrida

org.apache.maven.surefire.util.SurefireReflectionException: java.lang.reflect.InvocationTargetException; exceção aninhada é java.lang.reflect.InvocationTargetException: null java.lang.reflect.InvocationTargetException Causada por: java.lang.OutOfMemoryError: espaço PermGen

Eu tentei todos os acima dicas e truques úteis, mas infelizmente nenhum funcionou para mim. O que funcionou para mim é descrito passo a passo abaixo: =>

  1. Vá para o seu pom.xml
  2. Pesquise <artifactId>maven-surefire-plugin</artifactId>
  3. Adicionar um novo elemento <configuration> e sub elemento então <argLine> em que passar -Xmx512m -XX:MaxPermSize=256m como mostrado abaixo =>

<configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>

Hope isso ajuda, a programação feliz:)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top