Memória JAVA não abaixa

13 respostas
R

Estou com uma aplicação em JSF rodando em uma VM, toda vez que alguém está gerando relatório a memória do JAVA aumenta e não volta ao normal. Isso vai acontecendo até travar a maquina.

public void gerarRelatorio() throws JRException, SQLException, FileNotFoundException, IOException, ClassNotFoundException {
        
        try {

            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

            /* HashMap de parametros utilizados no relatório. Sempre instanciados */
            Map parameters = new HashMap();
            parameters.put("dataInicio", format.format(getDataInicio()));
            parameters.put("dataFim", format.format(getDataFim()));
            
            String where = "";

            if(codigoRegiao > 0){
                where = " and regiao.idRegiao = " + codigoRegiao + " ";
            }

            parameters.put("where", where );
            Class.forName("com.mysql.jdbc.Driver");
            Connection varConexao = DriverManager.getConnection("jdbc:mysql://localhost:3306/gope","root","java");

            byte[] bytes = JasperRunManager.runReportToPdf(PropertiesLoaderImpl.getPropriedade("CAMINHOJASPER") +      "AtendimentoPorPeriodo.jasper",parameters,varConexao);

            HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
            response.setHeader("Content-Disposition", "attachment;filename=\"" + "Analise_SLA "+new SimpleDateFormat("yyyyMMddhhmmss").format(new Date())+".pdf" + "\"");
            response.setContentType("application/pdf");
            response.setContentLength(bytes.length);

            ServletOutputStream ouputStream = response.getOutputStream();
            ouputStream.write(bytes, 0, bytes.length);
            ouputStream.flush();
            
            
            ouputStream.close();
            varConexao.close();

            FacesContext.getCurrentInstance().responseComplete();

        } catch (Exception e) { System.out.println("Erro em gerar o relatórios: " + e.getMessage()); }
       

}

13 Respostas

F

Ja respondemos muitas pessoas na mesma situação…segue minha resposta padrão:

java.lang.OutOfMemoryError: Java heap space:

Aplicação java esta precisando gastar mais memoria do que a alocada para JVM. Por isso acontece o erro de falta de memoria!

Trabalhar com memoria no Java é como uma brincadeira de criança…

  • a memoria é copo com um tamanho determinado.
  • cada vez que é criado uma variavel ou objeto (new), seria como se colocasse um gotinha ou gota de água nesse copo.

Como funciona?

  • Quando vc inicia a aplicação, ja acontece um gasto com um pouco de água…tipo uns 20% do copo (pelos gastos do objetos iniciais)
  • Enquanto a aplicação ta rodando, vai criando e executando os objetos, ou seja, vai enchendo de água esse copo.
  • Quando a água começa ficar em media acima dos 70% do tamanho disponivel ocupado, o GC ja vai se mover tentando retirar/derramar essa agua do copo (retirar os objetos sem referencia)
  • Se o gc conseguir, ele vai esvaziar o possivel e assim tudo volta ao ciclo repetitivo de uso. Vai usando e gastando denovo.
  • Se o gc não conseguir, a agua cai do copo e acontece o java.lang.OutOfMemoryError kkkkk

Motivos de Falta de Memoria?

  1. A solução esta gastando memoria desenfreadamente. Como?
  • Falta de uma arquitetura correta padrão.
  • Desenvolver despreparado, implementando código que gaste sem o devido controle.

Como corrigir?

  • Aprender praticas de otimização.
  • Entender o funcionamento da solução em questão.
  • Alterar o codigo da aplicação, aplicando as melhores praticas diante de cada situação.

2 A solução esta gastando memoria corretamente, mas ainda não é suficiente. O que fazer?:

  • Se a aplicação ja esta 100% otimizada, a única coisa que pode ser feito é aumentar a memoria! A solução precisa de mais memoria!!!
  • Situação muito comum em aplicações web quando o numero de usuário simultâneo vai aumento com o tempo.

java.lang.OutOfMemoryError: PermGen

PermGen quer dizer que a area de memória da JVM de carga de classes estouro…muito normal de acontecer quando um container JEE tem muita classes dentro própria aplicação + os jar’s para carregar.
Mais comum ainda quando o container JEE tem varios wars sendo executado simultaneamente.
Para corrigir isso, aumente essa area de memoria nos parâmetros do inicio do seu container.
Veja que isso não é um erro, é muito normal uma vez que cada container JEE deve ser devidamente configurado para o determinado ambiente/cenario a ser usado.

OBS - alterar o eclipse.ini muda os parâmetros para o eclipse e não para o tomcat!!!

No seu caso vc tem alterar os parâmetros de inicialização do tomcat diretamente no arquivo dele.
Se caso o tomcat esta sendo executado direto do eclipse, vc consegue acrescentar os parametros no seguinte menu:

  • Abra as propriedades do server clicando 2 vezes em cima do sevidor na aba “Servers”
  • Abra as configurações chamada de “Open launch configuration”
  • Selecione a aba “Arguments”, no campo VM arguments acrescente todos os seus parâmetros que customizam a memoria: Exemplo: -XX:MaxPermSize=246m
A

Utilizar um try{ } catch{ } finally{ } para garantir o fechamento do recurso também pode ajudar.

R

Fiz várias correções no código e mesmo assim o aumento de memória continua.

Não pode ser a configuração do Glassfish ?

J

Fera, estava com problema de memória também e verifiquei que na verdade eram as bibliotecas excessivas que constavam no meu projeto! Quando Retirei algumas, deu uma melhorada.

F

Sim…retire todos os JAR’s que não estão sendo usado, uma vez que é carregado no classloader, gastando PermGem.

R

Fiz alguns testes no fim de semana, acompanhei pelo JConsolte e percebi que o projeto não é está consumindo muito.

Mas o Java ainda continua crescendo, chega uma hora que a VM trava qdo o uso da cpu fica em 100% por causa do Java.

R

Tirei alguns JAR’s, mas a maioria deles estão sendo sendo utilizados. E ainda continua o problema.

F

O problema é memoria ou CPU?

R

O uso da memória do Java não parar de crescer, com isso o Uso de CPU vai subindo junto até travar a VM.

F

Um solução tem que ter um nível de memoria adequado para seu demanda de acesso:
Podem ser 3 coisas erradas:

  1. Nivel de memoria esta abaixo da sua demanda?
  2. Sua solução não esta liberando memoria devidamente?
  3. Opção 1 e 2 juntas.
G

Qual é a configuração de memória do seu glassfish ? Acredito que o problema seja no servidor e não na sua aplicação.

F

Sei que vai ser uma ajuda meio “inutil”, mas vc precisa olhar com cuidado seu codigo e verificar se existe algum memory leak.
Praticamente todas as vezes que me deparei com esse cenario era a aplicacao gastando memoria por más praticas mesmo de desevolvimento, que geravam objetos inelegiveis pra coleta, gasto desnecessario de recurso etc… nao é normal a memoria ficar sempre no talo, o normal é usar -> liberar.

R

Vamos lá, abaixo todas tentativas que melhoram o desempenho da aplicação, mas a memória do Java continua subindo.

[i]

  • Já revisei todos os meus objetos do jpa e defini como Lazy todos relacionamentos.
  • Dei um clear em todos EntityManager que a aplicação executava.
  • Quando o GC é executado a memória da aplicação desce no zero, mas a do Java continua.[/i]

Estou pesquisando sobre a memória heap.

E encontrei muita gente falando pra aumentar a memória young.

Vou tentar entender mais sobre este assunto e aplicar este teste. Talvez seja mesmo a configuração do Glassfish.

Criado 3 de novembro de 2011
Ultima resposta 8 de nov. de 2011
Respostas 13
Participantes 6