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 é&nbsp;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”