Coleta de lixo java no diálogo
* Estou agora encontrando um problema de GC muito estranho quando tento fazer um botão em um JFrame, e quando clico no botão, ele exibe um JDialog que precisa lidar e mostrar algumas imagens e precisa de quase 200M de memória. Mas o problema é quando eu fecho o diálogo e o reabro, às vezes ele causa java.lang.OutOfMemoryError. (não todas as vezes)
Tentando resolver o problema, simplifico esse problema e faço algumas experiências,o que me deixa mais confuso.
O código que usei no meu "experimento" é mostrado abaixo. Quando clico em um botão em um quadro, aloco 160 M de memória para um array inteiro e exibo um diálogo,Mas se eu fechar a caixa de diálogo e reabri-la, será exibido OutOfMemoryError. Eu ajustando o código e o resultado é:
Se eu não criar a caixa de diálogo e mostrá-la, não há problema de memória.Se eu adicionar um windowsCloseListener que invoque System.gc () para o diálogo, nenhum problema de memória.Se eu invoco System.gc () no método run (), o problema de memória é mostrado.
public class TestController {
int[] tmp;
class TDialog extends JDialog {
public TDialog() {
super();
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
// If I uncommment this code, OutOfMemoryError seems to dispear in this situation
// But I'm sure it not a acceptable solution
/*
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println("windowsclose");
TDialog.this.dispose();
System.gc();
}
});
*/
}
}
TDialog dia;
public void run() {
// If I do System.gc() here, OutOfMemoryError still exist
// System.gc();
tmp = new int[40000000];
for (int i = 0; i < tmp.length; i += 10)
tmp[i] = new Random().nextInt();
dia = new TDialog();
dia.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
final JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(200, 200);
JButton button = new JButton("button");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
TestController controller = new TestController();
controller.run();
controller = null;
}
});
frame.add(button);
frame.setVisible(true);
}
});
}
}
Eu li sobre muitos artigos que descrevem como o GC do java funciona. Eu acho que se java tentando alocar algum espaço no heap e ele não tiver espaço livre suficiente, o java fará o gc, e se um objeto não puder ser acessado da raiz do gc através do “GC graph”, no qual uma borda do u para v representa u tem uma referência para v, raiz é algo na pilha de trabalho de um encadeamento ou recursos nativos É inútil e qualificado para ser coletado pelo GC do Java.
Agora o problema é Quando clico no botão e tento criar um array Integer, o array Integer que criei na última vez certamente está qualificado para ser coletado pelo GC do java. Então, por que causou o erro.
Peça desculpas por uma descrição tão longa ... Não tenho muita tática para fazer o problema, apenas tentando deixar claro.
Além disso, o parâmetro que usei para iniciar o jvm é “java –Xmx256m”