# StackOverflow nach einem Tag Laufzeit



## Gast2 (22. Jan 2010)

Hi,
ich habe eine Swing Anwendung geschrieben, die bei mir nach ca. einem Tag Laufzeit Probleme macht.


> 2010-01-18 06:59:04,593 [AWT-EventQueue-0] ERROR: Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
> 2010-01-18 06:59:04,593 [AWT-EventQueue-0] ERROR: 	at java.awt.AWTEventMulticaster.mouseEntered(Unknown Source)
> 2010-01-18 06:59:04,593 [AWT-EventQueue-0] ERROR: 	at java.awt.AWTEventMulticaster.mouseEntered(Unknown Source)
> 2010-01-18 06:59:04,593 [AWT-EventQueue-0] ERROR: 	at java.awt.AWTEventMulticaster.mouseEntered(Unknown Source)
> ...



Diesen Feher bekomme ich, nachdem nach ca. einem Tag Laufzeit mit der Maus auf ein Label gehe. Auf diesem Label liegt eigentlich ein Listener der ein Popup anzeigt wenn draufgeklickt wird.
Nachdem diese Exception geworfen wurd friert dann auch die komplette GUI ein und ich darf das Programm neustarten.

Mir scheint, dass irgendwie EDT vorher schon irgendwie blockiert und durch diese Events dann dessen Aufrufstack überläuft. Lieg ich da mit meiner Vermutung richtig und muss daher woanders mit der Suche beginnen oder gibts ne andere Möglichkeit dem Problem auf die Schliche zu kommen?

Gruß,
Eike


----------



## MQue (22. Jan 2010)

Ich hatte das Problem mal, als bei mir mehrere Komponenten bzw. deren Listener zyklische Abhängigkeiten hatten, also wenn ich auf einen Button geklickt habe, wurde auch ein ActionListener eine anderen Komponente aufgerufen. Das ist eine mögliche Fehlerursache, nichts genaueres kann man aber nicht sagen, Schau dir mal die Anwendung mit einem Proofiler an und erzeuge ein paar Snapshots, dann siehst du, was sich in deiner Applikation so tut.


----------



## Meru (22. Jan 2010)

Ich würde erst mal nen Debugger durchjagen und dann Schritt für Schritt den Event-Process verfolgen.

StackOverflow kommt oft dadurch zustande, dass man eine Endlosschleife lostritt ala Rekursion oder massig Schleifendurchläufe ohne ersichtlichen Endes


----------



## Gast2 (22. Jan 2010)

Habs schon mit nem Debugger und Profiler versucht. Die ersten ersten Stunden läufts ja noch normal so wie es soll, aber wenn ichs mal nachts laufen lassen bekomme ich am nächsten morgen diesen Fehler.

Kanns denn sein dass ich nen Stackoverflow bekomme wenn die Events nichtmehr abgearbeitet werden können vom EDT ?
Ich bilde mir nämlich auch ein (obs wirklich so ist weiß ich nicht ) dass Teile der Anwendung auch nichtmehr richtig arbeiten, was mich vermuten lässt dass irgendwo nen Deadlock entstanden ist und sich nen Thread aufgehangen hat.


----------



## SlaterB (22. Jan 2010)

AWTEventMulticaster ist eine Klasse, die Events an zwei weitere EventListener weiterreicht,
AWTEventMulticaster ist selber auch so ein EventListener,
ein derartiges Objekt wurde bei sich selbst eingefügt, informiert sich für alle Ewigkeit selber

es ist fraglich ob du was damit zu tun hast, überprüfe aber allen Code, der mit Listener, add + remove zu tun hat,
wird in der Richtung im Laufe des Programms noch etwas gemacht?


----------



## Gast2 (22. Jan 2010)

Danke dafür erstmal, ich bin grad noch auf der Arbeit. Wenn ich wieder daheim bin werde ich das mal kontrollieren.
Mich wunderts halt, dass der Fehler nicht direkt auftaucht, sondern erst nach einigen Stunden. Wenn da irgendwelche Listener falsch miteinander verknüpft sind müsste der Fehler doch augenblicklich beim ersten mal auftauchen oder irre ich mich da?


----------



## SlaterB (22. Jan 2010)

das deutet auf einen unerklärlichen internen Bug hin, ja,
wenn du bei
Google
schaust, finden sich auch manche ähnliche Probleme, aber exakt dasselbe habe ich nicht gesehen bis auf genauso unschlüssiges wie
Swing - StackOverflowError from mouseEntered??


deshalb auch meine Frage, genau zu schauen, ob nicht nach einem Tag doch noch irgendeine relevante Änderung von deinem Code aus kommt,
sonst kann man wenig machen außer Hoffen/ Versions-Wechsel/ die Stelle finden und mühsam was drumherum kitten,
nach einem Testprogramm frage ich gar nicht erst, wenn man einen Tag warten muss


----------



## Gast2 (22. Jan 2010)

Hab mich durch die Googleergebnisse mal ein wenig durchgelesen und nochmal durch meinen Code geschaut.

Ich fürchte ich hab den Fehler gefunden:


```
t = new Timer(5000, new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        updateConnectionCountLabels();
    }
});
t.setRepeats(true);
t.start();
```


```
public void updateConnectionCount() {
    statusActiveConnectionCount.setText(ConnectionManager.getActiveConnectionCount()+"");
    updateActiveConnectionCountPopup();
}

private void updateActiveConnectionCountPopup() {
    /* Popup leeren */
    connectionCountPopup.removeAll();
    JLabel item;
    ArrayList<BasicConnection> activeConnections = ConnectionManager.getActiveConnections();
    if (activeConnections.size() == 0) {
        connectionCountPopup.add(item = new JLabel("keine aktive Verbindungen"));
    } else {
        connectionCountPopup.add(item = new JLabel("Aktive Verbindungen: "));
    }

    /* Schriftart laden */
    Font f_plain = new Font(Settings.getString("MAINFRAME", "popup.fontfamily"), Font.PLAIN, Settings.getInt("MAINFRAME", "popup.fontsize"));
    Font f_bold = new Font(Settings.getString("MAINFRAME", "popup.fontfamily"), Font.BOLD, Settings.getInt("MAINFRAME", "popup.fontsize"));
    item.setFont(f_bold);

    for (int i = 0; i < activeConnections.size(); i++) {
        BasicConnection con = activeConnections.get(i);
        connectionCountPopup.add(item = new JLabel(con.toString()));
        item.setFont(f_plain);
    }

    connectionCountPopup.setLabel("ActiveConnections");
    connectionCountPopup.setBorder(new BevelBorder(BevelBorder.RAISED));
    connectionCountPopup.setVisible(false);

    MouseAdapter mouseListener = new MouseAdapter() {
        public void mousePressed(MouseEvent e) { checkPopup(e); }
        public void mouseClicked(MouseEvent e) { checkPopup(e); }
        public void mouseReleased(MouseEvent e) { checkPopup(e); }

        private void checkPopup(MouseEvent e) {
            if (!connectionCountPopup.isVisible() && (e.isPopupTrigger() || e.getButton() == MouseEvent.BUTTON1)) {
                connectionCountPopup.show(statusActiveConnectionCount, 0, -connectionCountPopup.getHeight());
                connectionCountPopup.show(statusActiveConnectionCount, 0, -connectionCountPopup.getHeight());
                // Doppelt ausführen damit größe des Popups richtig verwendet wird... buggy?!
            }
        }
    };
    statusActiveConnectionCountLabel.addMouseListener(mouseListener);
    statusActiveConnectionCount.addMouseListener(mouseListener);
}
```

Ich denke es ist nicht sinn der Sache immer nen neuen MouseListener hinzuzufügen, oder? 
Den MouseListener hatte ich deswegen neu erstellt, damit die Position des Popups immer richtig ist. Die untere linke Kante des Popup soll an die rechte obere Kante eines Labels... musste da auch den show befehl zweimal ausführen, damit er mir die Position richtig berechnet. getHeight() hatte da immernoch den wert vom vorherigen Popup. (nen pack() sollte es doch da tun oder?)
Herrlich auf was für ideen man immer während des Tippens kommt :bae:

Nun die Frage wie ich die Listener die am statusActiveConnectionCount und statusActiveConnectionCountLabel hängen entfernen kann. Sollte ich mir ne Referenz auf den Listener speichern und den vorm hinzufügen des neuen wieder entfernen.
Oder besser den Listener nur einmal hinzufügen und im checkPopup() nen pack ausführen?

EDIT:
pack(), validate() oder doLayout() helfen leider nicht, also doch zweimal show aufrufen?


----------



## SlaterB (22. Jan 2010)

ich verstehe nicht so richtig worum es geht und warum doLayout() was mit dem Listener zu tun hat,
aber will auch gerade nicht angestrengt nachdenken 

nur als Grundlage: Listener immer (oder eben jetzt wenn es Probleme gibt) nur genau einmal und am Anfang adden, 
wenn man sie zwischenzeitlich deaktivieren will kann man im inneren per if die Aktivität steuern

bei neuen Komponenten muss man sicherlich auch neue Listener adden,
evtl. nur vorhandene verschieben? aber zu deinen Popups usw. kann ich grad nix genaues sagen


----------



## Gast2 (23. Jan 2010)

Sry, das mit dem StackOverflow und dem doppelten Aufruf von show() waren zwei verschiedene Probleme. 
Durch den Timer adde ich jede 5sek einen neuen Mouselistener, ich denke daher kommt dann auch der Stackoverflowerror, oder nicht? Den Mouselistener würd ich dann nur einmal hinzufügen beim start des progs.
Das zweite prob ist, dass ich connectionCountPopup.show() zweimal aufrufen muss, damit er die größe richtig erkennt, und da wollte ich einfach pack, validate oder doLayout vorher ausführen, damit er die Größre direkt richtig ausliest, aber das funktioniert leider nicht. Also werde ich wohl bei zwei show aufrufen bleiben müssen, oder gibts da ne andere lösung?


----------



## Gast2 (23. Jan 2010)

EikeB hat gesagt.:


> Durch den Timer adde ich jede 5sek einen neuen Mouselistener, ich denke daher kommt dann auch der Stackoverflowerror, oder nicht?


nein ... unter Strich kommt nur jedesmal ein neuer einfacher Funktionsaufruf hinzu ... ein StackOverflow erhälst Du aber nur bei einem rekusiven Funktioneausruf - oder wenn die Aufruftiefe zu tief ist bzw. der Stack mit lokalen Variablen bombardiert wird


```
handleMouseEvent();
handleMouseEvent();
handleMouseEvent();
handleMouseEvent();
handleMouseEvent();
// ... und weiter
```



> Den Mouselistener würd ich dann nur einmal hinzufügen beim start des progs.


ist zu empfehlen - wie schon geschrieben


----------



## Gast2 (24. Jan 2010)

Danke, durch das abändern des MouseListeners ist das Problem nun behoben


----------

