Como evitar memory leaks com swing?

6 respostas
vitimnunes

Pessoal, venho sofrendo já a algum tempo com essa batalha e por muitas vezes cheguei a considerá-la perdida.
Criei um twitter client em Swing, mas percebi que o consumo de memória (usando taskmanager do windows) que o consumo de memóia crescia indefinidamente.
Pois bem, segui várias dicas, tutoriais para encontrar e remover memory leaks mas tudo em vão, resolvi então reescrever a aplicação toda.
Mas antes de fazê-lo gostaria de saber se há algumas dicas ou alguns métodos de programação que evitem o surgimento desse indesejável problema na minha aplicação.

De início digo que minha aplicação trabalha muito com loops de repetição, abertura de diálogos e atualização da interface com validate(); e repaint();
Alguém pode me ajudar?

6 Respostas

ViniGodoy

Eu acho estranho que você esteja tendo leaks com o Swing.

Mas algumas dicas seriam:

  1. Evite ao máximo o uso de variáveis estáticas;
  2. Lembre-se que listeners também podem manter objetos vivos;
  3. Use profilers se tiver leaks;

Na programação Swing, é muito pouco provável que você tenha que chamar repaint() diretamente. Se isso está acontecendo, é um mal cheiro de código.

vitimnunes

pois é, estou utilizando swing. tento sempre usar AbstractActions ai invés de ActionListener, faz alguma diferença?
na janela principal da aplicação eu uso da seguinte maneira

public class MainWindow extends JFrame implements WindowListener {
  private static final MainWindow instance = new MainWindow();

  public MainWindow() {
    super();
  }

  public static MainWindow getInstance() {
    return instance;
  }
}

preciso que diálogos manipulem essa instancia, por isso fiz assim, mas acredito que possa ser mudado, estou tentando usar GroupLayout para fazer o posicionamento.
Confesso que o VisualVM não me ajudou muito. =/

ViniGodoy

Nenhuma diferença.

vitimnunes:
na janela principal da aplicação eu uso da seguinte maneira

public class MainWindow extends JFrame implements WindowListener {
  private static final MainWindow instance = new MainWindow();

  public MainWindow() {
    super();
  }

  public static MainWindow getInstance() {
    return instance;
  }
}

A janela principal nunca será coletada. Nem qualquer coisa que ela referencie. Nem qualquer listener que qualquer objeto que ela tenha aponte. A menos, claro, que você remova os listeners ou limpe as referências diretamente.

vitimnunes:
preciso que diálogos manipulem essa instancia, por isso fiz assim, mas acredito que possa ser mudado, estou tentando usar GroupLayout para fazer o posicionamento.
Confesso que o VisualVM não me ajudou muito. =/

Você chegou a usar a opção de rastrear o objeto que está mantendo a referência viva? Geralmente em memory leaks fazer isso por amostragem ajuda. Chegou a usar o profiler do Netbeans? Ele é mais poderoso que o VisualVM.

vitimnunes

na realidade, sempre que eu iniciava qualquer profiler (tanto VisualVM quanto o do NetBeans) a aplicação quebrava e saia.
=/

reportei várias vezes à sun (hoje oracle) mas nada…
estou removendo então o uso do getInstance() na janela principal, vou tentar passar como parâmetro para os construtores das classes que necessitam…
realmente nao sabia que essa forma de criar e gerenciar a instância de uma janela poderia ser prejudicial…

conforme for fazendo as alterações vou postando os resultados… vlw

vitimnunes

quando você disse:

a que você se referia, como eu faria essa remoção manual?

ViniGodoy

Você chegou a usar o parâmetro -XX:+HeapDumpOnOutOfMemoryError na sua VM?
Aí vc roda a aplicação normal, e ele gera o heap dump só quando ela estoura. O heap dump então você abre no profiler. Pode ser uma opção.

vitimnunes:
estou removendo então o uso do getInstance() na janela principal, vou tentar passar como parâmetro para os construtores das classes que necessitam…
realmente nao sabia que essa forma de criar e gerenciar a instância de uma janela poderia ser prejudicial…

Se a janela vai ficar sempre aberta, não faz muita diferença. Se ela irá fechar, aí é melhor fazer o fechamento correto, sem o static, para que ela pare de ocupar memória enquanto fechada.

Assim como tem métodos de “addXXXListener” existem os métodos de “removeXXXListener”. Normalmente isso não é necessário, pois quando o pai morre, a lista de listeners morre junto. Porém, algum listeners podem ter referências estáticas a alguma classe pai e, se não forem coletados, tudo a que se referenciam não será também.

Mas geralmente, essas situações quem indica é o profiler.

Criado 19 de setembro de 2010
Ultima resposta 20 de set. de 2010
Respostas 6
Participantes 2