Speicherverwaltungsbug bei java6 bei Swing/AWT?

  • Themenstarter Themenstarter Jan_HH
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
J

Jan_HH

Gast
Hallo,

bei meinem Programm werden (aus was für Gründen auch immer) diverse Swing-Fenster (JFrame) nacheinander dargestellt. Ein Fenster wird angezeigt, nach Klick auf einen Button verschwindet es, und das nächste wird angezeigt. Die Fenster an sich (also die JFrame-Objekte) sind allesamt bereits erzeugt worden, bevor das erste Fenster angezeigt wird (es werden also während des Ablaufs KEINE neuen Objekte erstellt).

Bei java bis einschliesslich 5/1.5 hat alles funktionert, aber ab java 6 verhält es sich nun so, dass ein Fenster beim Anzaigen ca. 3 MB Speicher verbraucht (erkennbar im Windows-Taskmanager), die nicht wieder freigegeben werden, wenn das nächste Fenster an der Reihe ist. Der Speicher wird also nach und nach immer knapper, vollgemüllt mit was auch immer. Da sich java bis einschliesslich Version 5 nicht so verhalten hat (da blieb der Speicherbedarf der Anwendung die ganze Zeit über konstant), liegt die Vermutung nahe, dass es sich um einen Bug bei java 6 handelt. Da dieser aber auch in der allerneuesten Version (update 5) noch vorhanden ist, kann es ja auch sein, dass es doch kein Bug ist, sondern eine geändert Verhaltensweise von java. Was ziemlich mies wäre, weil es quasi das aus für mein Programm bedeuten würde.

Hat irgendjemand Ahnung davon, oder ist dieser Effekt schonmal jemandem begegnet?

Gruß
Jan
 
einen bug in java6 zu vermuten ist sehr gewagt. ausschließen will ich das nicht, aber ich vermute eher ein problem in deinem code 😉 entweder ein simples memory leak (z.b. werden die referenzen auf bereits geschlossene fenster noch vorgehalten), das in java5 nicht aufgefallen ist oder, noch viel einfacher, der GC hat plötzlich schlechtere laune.

java garantiert nicht, dass speicher sofort wieder freigeräumt wird. nen erster hinweis, ob nen memory leak vorliegt oder der GC lahmt ist, wenn der heap space vollläuft und die jvm aussteigt. dann hat in 95% der fälle auch der GC nichts mehr retten können.
 
Mit fenster.dispose() sollte der Speicher wieder freigegeben werden. Das heißt aber NICHT, dass der TaskManager sofort weniger Speicher anzeigt. Der Speicher, der "freigegeben" wurde, ist immeroch für die JVM reserviert. Etwas unpäzise(!) formuliert: Der Speicher wird erst "echt" freigegeben, wenn neuer Speicher angefordert wird, und der verfügbare Speicher nicht ausreicht. Man könnte (auch wieder etwas unpräzise) sagen, dass ein "Fehler" nur dann vorliegt, wenn irgendwann ein OutOfMemoryError kommt - wenn der nicht kommt, ist alles in Ordnung.
 
Genau der kam aber.. das ist ja das Problem. Pro Fenster ca. 3 MB mehr, bis irgendwann Speicher voll. Den Exceptions nach, die da kamen, klang es so, als ob ein Bitmap-Objekt zum Zeichnen des Fensterinhalts erzeugt und später nicht wieder freigegeben wird.. kann das sein? Aber wie gesagt, in java < 6 trat nichts derartiges auf. Natürlich gibt es noch Referenzen auf die Fenster, ihr Inhalt wird ja später noch benötigt.. aber die Fenster-Objekte werden eh alle schon im Vorfeld erzeugt, sie werden später lediglich angezeigt und wieder ausgeblendet. Und es kann doch wirklich nicht sein, dass eine Applikation, die 100 Fenster benötigt, so viel Speicher verbrät, dass das Programm mit einer Exception abstürzt!? Selbst wenn das kein Bug sein sollte, ist es zumindest höchst unsinniges Design. Kann mir wirklich nicht vorstellen dass es sich so verhalten soll.
 
Jan_HH hat gesagt.:
Und es kann doch wirklich nicht sein, dass eine Applikation, die 100 Fenster benötigt, so viel Speicher verbrät, dass das Programm mit einer Exception abstürzt!?
Wenn sie nicht wieder freigegeben werden: natürlich.
Wo soll der Speicher denn herkommen? Es handelt sich um eine begrenzte Resource.
 
Dann hätte der Fehler aber auch schon mit java < 6 auftreten müssen,oder?
 
Nein, auch mit Java 5 gab es keine unbegrenzten Resourcen.
Welches Verhalten erwartest du wenn du immer mehr und mehr auf den Heap packst?
 
Wildcard... die Resourcen wurden anscheinend vor Java 6 nach dem Schließen freigegeben, jetzt nicht mehr. Hat der OP doch geschrieben, und wieso sollte er das erfinden?

@OP Verwendest du sicher den gleichen Code mit beiden Versionen? Rufst du dispose() auf um die Fenster zu Schließen? Sonst fällt mir nämlich leider auch nix ein.
 
Illuvatar hat gesagt.:
Wildcard... die Resourcen wurden anscheinend vor Java 6 nach dem Schließen freigegeben, jetzt nicht mehr. Hat der OP doch geschrieben, und wieso sollte er das erfinden?
Natürlich gibt es noch Referenzen auf die Fenster, ihr Inhalt wird ja später noch benötigt..
Das sie dann nicht komplett freigegeben werden können, ist doch klar.
 
Verwirrung.. aaalso.. ein Aufruf von dispose() löst das Problem in der Tat. Vielen Dank!

Das Problem tritt NUR bei java 6 auf, bei 1.4 und 1.5 nicht (mit natürlich genau dem gleichen Programmcode).

Ich packe auch NICHT immer mehr Objekte auf den heap.. ich erzeuge n Fenster, und zeige eins nach dem anderen an. Ich erzeuge sie nicht direkt vor dem Anzeigen, sondern schon vorher alle auf einmal. Dabei wird natürlich eine bestimmte Menge Speicher verbraucht, aber die bleibt danach dann auch mehr oder weniger konstant.

Es ist wohl also kein Bug, aber schon sowas wie "inkonsistentes Verhalten". Ich vermute, dass java-intern die ganze Fensterdarstellung kompett ungebaut wurde, und mittlerweile braucht ein AWT-Fenster halt irgendein 3 MB grosses Objekt, um sich zeichnen zu können (würde ja auch passen, BildschirmbreitxBildschirmhöhex24 bit Farben = ca. 3 MB), und das war bei java 5 noch nicht so. Der eigentliche Bug dürfte in meinem Programm sein, das dispose() vergessen zu haben.
 
Hi,

ich habe das gleiche Problem. Habe eine Datanbank im Hintergrzud laufen und hole meine Datan aus ihr. Das jeweillige Jcomponent beobachtet (Observer) die Datenbank-Anweisungs- Klassen. Sobald eine Anweisung ausgeführt worden ist, meldet die der entsprechnder Klasse aus dem Frontend (die von JComponent abgeletet is) das Egebnis. Darauf hin werden in diesem jComponen neue Componenten (Jpanel, Jtextfield.. ect. ) gesetzt oder ersetzt. Beispielsweise jabe ich eine JTable, sobald Daten den von den Datenbank-Anweisungs- Methoden mit notifyobserver dem zugeförigen angemeldeten observer übermittelt werden, wird eine neue Jtable (mit diesen daten Gefüllt). Dazu überschreibe ich einfach die alte Jtabel. Das Problem ist, dass die alten Daten der Jtabel immer noch im speicher bleiben und die neuen den Speicher füllen.

Wenn ich die Anweisung 50 mal ausführe, bewirkt dies den Überlauf des Heaps. Dispose() kann ich nicht ausführen, da ich nur mit einem Jframe arbeite..... alle anderen Klassen leite ich von JComponent ab (setzte den Lyoutmanager ect. ).

Könnt ihr mir weiter helfen?
 
Wenn du die alten Daten nie weg wirfst, wird natürlich der Speicher überlaufen. Wieso legst du überhaupt immer neue JTables an? Benutze ein TableModel, dem du die Daten aus der DB übergibst. Wenn es keine Referenzen auf die alten Objekte gibt, sollte das Problem nicht mehr auftreten.
 
tfa hat gesagt.:
Wenn du die alten Daten nie weg wirfst, wird natürlich der Speicher überlaufen. Wieso legst du überhaupt immer neue JTables an? Benutze ein TableModel, dem du die Daten aus der DB übergibst. Wenn es keine Referenzen auf die alten Objekte gibt, sollte das Problem nicht mehr auftreten.


Hey Tfa, ich hab das Problem gefunden. Meine klasse waren noch in den Observer angemeldet. Ich habe die dann mittels deleteObserver(klasse) gelöscht. 🙂
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben