Speicherleck?

meister-g

Bekanntes Mitglied
Hallo zusammen,

ich arbeite an einer Software, in der Messungen durchführt werden.
Dazu gibt es diverse Diagramme und Datenstrukturen... wenn alles fertig ist, wird alles in ein File geschrieben und man kann die nächste Messung machen.

Nach Programmstart belegt das Programm ca. 50mb
Nach einer Messung sind es 65mb.
Mache ich nun viele Messungen, z.B. 10 nacheinander wächst der Speicher im Taskmanager auf ca 120mb und und teilweise "friert" dann das Programm dann irgendwann einfach ein. Keine Exception. Repaint funktiniert nicht und die Anwendung reagiert träge bis gar nicht.

Bei jedem Testneustart wird offensichtlich Speicher freigegeben (clear()-Methoden und Neurefernzierungen), er kommt aber nicht annähernd auf den Wert zurück, den das Programm vor/nach dem ersten Test hat.

Ich habe jetzt die Vermutung, dass ich irgendwo ein Speicherleck habe... aber wo?!
Wie suche ich hier?

Neue Objekte bei neuer Messung/während einer Messung werden hauptsächlich hier erzeugt:
- GUI: eigentlich kaum - initial alles erstellt und ins Layout eingefügt und entfernt
- Datenmodell: Einige Listen (ArrayList) mit Objekten - Das wird bei jeder neuen Messung ge-clear()-ed.
- Charts: Diverse JFreeCharts; diese Erzeuge ich, adde sie. Später clear() ich sie und remove() sie aus dem Layout. Dann wird ein neues erzeugt etc.
- Timer: Existieren sehr viele in dem Programm. Diese cancel() ich und erzeuge jeweils einen neuen, den ich starte. Kann man her mehr machen außer cancel()

Ansonsten fallen mir noch einige Observer-Listen ein. Hier bin ich aber ziemlich sicher, dass Objekte immer wieder passend aus den Observer-Listen entfernt werden.

Nun meine konkreten Fragen:
Was der oben genannten Punkte ist "ein Klassiker" bei Speicherlecks? Wo vermutet man das Problem?
Gibt es Strategien/Tools um herauszufinden wo die Speicherlecks ind bzw wofür der ganze Speicher benötigt wird?
Sollte ich den Garbage Collector explizit aufrufen? (mache ich nicht)
Kann ich das "Einfrieren" des Programms irgendwie verhindern/erkennen?

Und evtl eine ganz Dumme Frage zu dem Thema:
Was passiert bzw ist es falsch, wenn ich ein Member-Objekt = null setze bzw gleich neu zuweise (= new Object())?
Dann wird doch das alte Objekt durch den GarbageCollector aus dem Speicher genommen, weil es die einzige Referenz war, richtig?!
Ebenso, wenn ich GUI-Elemente erzeuge, einem Container add()e und mit remove() oder removeAll() entferne (und keine weitere Referenz besteht), oder?!
 
G

GladstoneGander

Gast
Da gibt es einen guten Artikel vom Java Magazin: http://www.dynatrace.com/de/pdf/Javamagazin_06_2009.pdf

An Tools gibt es z.B. für Eclipse integriert den MemoryAnalyzer (gibt es auch als eigenständige Anwendung). Dafür musst du zur Laufzeit aber einen Heap-Dump erstellen, den du dann einliest. Wenn du NetBeans verwendest, empfehle ich dir aber den Profiler (Menü: Profile->Profile Main Project).

Es werden dir in beiden Tools sämtliche Objektinstanzen angezeigt. Dort kannst du dann gucken, wieviele Instanzen einer Klasse gerade vorhanden sind und warum (=wer hat noch Referenzen darauf).

Das ganze Auswerten ist aber sehr zeitintensiv. Der Aufwand lohnt sich aber, wenn du die Vermutung hast, dass etwas bei deinem Programm nicht stimmt.

Gruß
 

meister-g

Bekanntes Mitglied
ok, danke für die antworten.

ich vermutete schon, dass ich hier voll auf dem schlauch stehe oder eben mit tools und viel zeit ran muss.

falls noch jemand klassiker an fehlern parat hat, kann er sie hier gerne posten.

hab aber schon einen ansatz... meine timer (TimerTask) sind/waren wohl nicht ganz sauber.
diese haben referenzen auf objekte, die bestehen bleiben.
gecancelt sind diese wohl weiter im speicher und davo nehmen sie nicht wenig.
jetzt weise ich den Objekten in der Methode cancel() null zu.
Sieht aus, als wäre damit (zumindest ein teil) meines speicherproblems gelöst.
 

Wildcard

Top Contributor
ich vermutete schon, dass ich hier voll auf dem schlauch stehe oder eben mit tools und viel zeit ran muss.
Du überschätzt die Aufgabe. Benutze wie maki sagt die VisualVM und ziehe dir einen Heap Dump. Einfache Probleme kann man direkt in der Visual VM identifizieren (keine Sorge, die Daten sind schön aufbereitet, das dauert nur ein paar Minuten), wenn es komplexer wird ist Eclipse MAT das richtige Tool.
 

meister-g

Bekanntes Mitglied
ich habe jetzt erst einmal ohne heap analyzer meinen code nachgebessert.
programmspeicher vergrößert sich jetzt nicht mehr so schnell. und nach einiger zeit wird er fast komplett freigegeben.

start software: 50mb
läuft länger - mehrere messungen: 85mb
(daziwschen sollte eigentlich schon freigegeben werden)
plötzlich im leerlauf (vor einer neuen messung): 30mb

- ist das normal, dass speicher auch ohne speicherleck nicht wieder (sofort) frei gegeben wird?
- ist es normal, dass der speicher irgendwann (bei mir im leerlauf nach einigen minuten! und erst recht nicht da wo ich eine speicherfreigabe erwarte) quasi komplett freigegeben wird?
 

Wildcard

Top Contributor
- ist es normal, dass der speicher irgendwann (bei mir im leerlauf nach einigen minuten! und erst recht nicht da wo ich eine speicherfreigabe erwarte) quasi komplett freigegeben wird?
Der GC läuft nicht nur wenn der Speicher knapp wird, oder wenn die Applikation idle ist, das ist also völlig normal.
 
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben