java Müllabfuhr im Dialog

* Ich stoße jetzt auf ein sehr seltsames Java-GC-Problem, wenn ich versuche, eine Schaltfläche in einem JFrame zu erstellen, und wenn ich auf die Schaltfläche klicke, wird ein JDialog angezeigt, der einige Bilder verarbeiten und anzeigen muss und fast 200 MB Speicher benötigt. Aber das Problem ist, wenn ich den Dialog schließe und wieder öffne, manchmal verursacht es java.lang.OutOfMemoryError. (nicht jedes mal)

Bei dem Versuch, das Problem zu lösen, vereinfache ich dieses Problem und mache einige Experimente.was mich verwirrter macht.

Der Code, den ich in meinem "Experiment" verwendet habe, ist unten gezeigt. Wenn ich auf eine Schaltfläche in einem Frame klicke, reserviere ich 160 MB Speicher für ein ganzzahliges Array und zeige ein Dialogfeld an.Wenn ich das Dialogfeld schließe und es erneut öffne, wird OutOfMemoryError angezeigt. Ich passe den Code an und das Ergebnis ist:

Wenn ich den Dialog nicht erstelle und ihn nicht zeige, liegt kein Speicherproblem vor.Wenn ich einen windowsCloseListener hinzufüge, der System.gc () zum Dialogfeld aufruft, tritt kein Speicherproblem auf.

Wenn ich System.gc () in der run () -Methode aufrufe, wird ein Speicherproblem angezeigt.

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);
      }
    });
  }
}

Ich habe über viele Artikel gelesen, die beschreiben, wie die GC von Java funktioniert. Ich denke, wenn Java versucht, etwas Speicherplatz im Heap zuzuweisen und es nicht genügend freien Speicherplatz hat, wird Java gc ausführen, und wenn über "GC graph", in dem eine Kante von "gc root" ist, nicht auf ein Objekt zugegriffen werden kann u bis v repräsentieren u haben einen Verweis auf v, root ist etwas im Arbeitsstapel eines Threads oder nativen Ressourcen. Es ist nutzlos und qualifiziert, von Java GC gesammelt zu werden.

Jetzt ist das Problem&nbsp;Wenn ich auf die Schaltfläche klicke und versuche, ein Integer-Array zu erstellen, ist das Integer-Array, das ich zuletzt erstellt habe, mit Sicherheit für die Erfassung durch den Java-GC qualifiziert. Also warum hat es Fehler verursacht.

Entschuldigen Sie sich für solch eine lange Beschreibung ... Ich habe nicht viel Taktik, um ein Problem zu stellen, also versuche ich nur, es klar zu machen.

Außerdem ist der Parameter, mit dem ich jvm gestartet habe, "java –Xmx256m".