Vazamento de memória

12 respostas
zerokelvin

Salve pessoal,

seguinte: tenho um servidor que lança as threads para cada cliente. Há um tempo, qdo preciso manipular algum array de byte maior (entre 5 e 20 megas) tenho um estouro na heap… há maneiras alternativas deu fazer isso, mas fui tentar mexer dessa forma… dae fiz a analise pela visual VM, e o que toma espaço nesse servidor são bytes[]… mas mesmo antes deu instanciar QUALQUER byte[] ele já utiliza 18 megas nesses objetos!!!

Ou seja: antes de instanciar o 1º byte[], ele já utiliza 18 megas, dae qdo chamo o grandão, a memória estoura.

Pergunta: utilizo como forma de comunicação o ObjectInput/OutputStream… é isso? nesse objectin/outstream há uma conversão para byte[] que preciso limpar depois de utilizar???

12 Respostas

ViniGodoy

O byte[] é a estrutura básica de diversas classes, como a classe String ou os ObjectInputStream/OuputStream. Para uma análise mais consistente, você tem que tentar rastrear na sua Visual VM que objetos são os donos desses byte[].

E

Veja o método reset, provavelmente você terá de chamá-lo a cada vez que enviar um objeto pela rede.

zerokelvin

Tem como eu fazer esse detalhamento pela visualvm? olhei lá, o que vi é o “heap dump” que detalha os objetos, mas como faço para achar isso no código?

entanglement, valeu! acho q isso já vai ajudar bem!

ViniGodoy

No código é mais complicado, porque não é trivial rastrear onde a alocação ocorreu. O negócio é mesmo identificar as classes, e procura-las em seu código. Parece que o profiler no Eclipse tem recursos melhores para isso.

zerokelvin

Tentei aki, mas nao manjo nada do eclipse. Alguem sabe algum tutorial? procurei profiler do eclipse no google e nao achei…
valeu por enquanto

E

Para achar as coisas, é melhor procurar por “TPTP Eclipse tutorial”. Procurar por “Profiler do Eclipse” não acha muitas coisas interessantes.

E

Tio, ouvi falar até de gente que foi despedida porque não conseguiu resolver problemas de vazamento de memória com ObjectInput/OutputStream encapsulando um Socket - e não usou o danado do “reset” no ObjectOutputStream a cada vez que dava um writeObject. Que tal tentar isso antes de mais nada?

Alexandre_Saudate

Putz, não acha que é um pouco de exagero, uma demissão por causa disso ?

[]´s

zerokelvin

Eu não me demitiria hehehehehehheeh, mas daria um pito!
aparentemente era isso do reset, mas a quantidade utilizada de memória ainda é alta, vou continuar analisando.
valeu memo!

E

Putz, não acha que é um pouco de exagero, uma demissão por causa disso ?

[]´s

Bom, o cara foi despedido, não exatamente por causa disso, mas porque um monte de gente não topava muito com a cara dele, que ele era muito teimoso, e não quis saber dessa tal correção que foi proposta. Ele achava que era o usuário que estava fazendo as coisas errado.

J

zerokelvin:
Eu não me demitiria hehehehehehheeh, mas daria um pito!
aparentemente era isso do reset, mas a quantidade utilizada de memória ainda é alta, vou continuar analisando.
valeu memo!

Se a quantidade é alta, uma boa opção é rever o algoritmo. Pode ser que você possa otimizá-lo, utilizando recursos diferentes que possam resolver o mesmo problema.

zerokelvin

Cara, to ficando doido… utilizei já a visualvm e o profiler do eclipse…

no caso, a utilização do reset() diminuiu o dispendio total de memória, mas agora tá acontecendo algo relacionado

O código abaixo roda num servidor, o método é acessado por uma chamada simples… tanto o blob quanto o rs morrem no próprio metodo… então teóricamente esse byte[] vindo do banco de dados nao “persistiria” na memória ram…

public void BaixarArquivo(String s, ObjectOutputStream ostream){
         try{
            System.out.println(s);
            PreparedStatement stmt = cmysql.prepareStatement(s);
            ResultSet rs = stmt.executeQuery();
            rs.first();
            Blob b = rs.getBlob("ARQUIVO");
            rs=null;
            
            System.out.println("Enviando arq");	
            
            
            ostream.writeObject(b.getBytes(1, (int)b.length()));
            ostream.reset();
         	
                    
            b = null;
            
         }
             catch(Exception e){e.printStackTrace();}
      }

MAS qdo baixo uma sequencia de arquivos, acesso várias vezes o método seguidamente, a memória dá um boom, e cai a thread do servidor.
O engraçado é q a memória vai acumulando as operações, por exemplo: na 3ª vez que baixo 10 arquivos (os mesmos baxados na 1ª e 2ª vez), a heap estoura, o profler mostra um acumulo de uns 60 megas no ram, em byte[]!!!

já inclusive joguei um System.gc(); depois do b=null, mas nao adiantou… alguem tem idéia do q é?

Criado 17 de agosto de 2010
Ultima resposta 22 de ago. de 2010
Respostas 12
Participantes 5