Problem mit dem Heap Space (Speicherüberlauf)

oetzi

Bekanntes Mitglied
Hallo zusammen,

mir läuft der Heap Space voll, ich komme aber nicht auf die Ursache des Problems.


Ich beschreibe mal was mein Programm macht:
Allgemeine Infos:
- Das Programm analysiert die Logdateien eines Lasttestlaufs und schreibt verschiedene Daten wie IDs und natürlich vorallem die Laufzeit in eine CSV Datei.
- Eine Logdatei ist so aufgebaut, dass sie unter anderem Zeilen wie "Starte Versand..." und "Erhalte Antwort..." neben jede Menge anderen Logeinträgen enthält.
- Stündlich wird eine neue Logdatei geschrieben, somit teilt sich ein Testlauf auf mehrere Logdateien auf.

Ablauf des Programms:
1. Einlesen der ersten Logdatei. Dabei werden alle Zeilen, die die Schlüsselworte "Starte Versand..." und "Erhalte Antwort..." enthalten in ein String-Array geschrieben.
2. Aufruf einer Methode, die dieses Array auswertet, d. h. aus jeweils einem Start- und dem passenden Antwort-Eintrag wird eine Zeile für die CSV Datei zusammengebastelt.
2.1 Löschen der beiden gerade bearbeiteten Einträge aus dem Array. Dies habe ich gemacht, weil ich dachte, dass dieses Array für den Speicherüberlauf verantwortlich ist. Leider hat das nichts gebracht.
3. Einlesen der nächsten Logdatei, usw.

Ich habe mal eine Ausgabe eingebaut, die nach jeder analysierten Logdatei erzeugt wird und die mir den verbleibenden Speicherplatz anzeigt (Runtime.getRuntime().freeMemory()). Dabei sehe ich, dass jedes mal ca. 60-80Mb flöten gehen. (Die Logdateien sind übrigens ca. 40Mb groß)

Mir fehlt jetzt wohl das tiefere Verständnis vom Speichermanagement von Java. Bis jetzt war ich mit der Info ganz gut bedient, dass der garbage collector den Speicher wieder aufräumt sobald man die Zeiger auf die jeweiligen Objekte entfernt.
Mache ich das nicht, wenn ich per remove die Einträge aus dem Array entferne?

Gibt es sonst noch irgendwelche Java-typischen Speicherfallen in die man reintreten kann?

Wo ich mir noch nicht sicher war ist der bufferedWriter bzw. bufferedReader. Hier habe ich sicherheitshalber ein flush (writer) eingebaut und den reader "close" ich sobald ich ihn nicht mehr benötige. Aber brauchen bufferedWriter/Reader überhaupt viel Speicherplatz?

Sonst fällt mir überhaupt nicht mehr ein, wo mein Speicherfresser versteckt sein könnte.

Hoffe, dass mir da wer einen Tipp geben kann.

Schönen Gruß
oetzi

PS: Habe den Heapspace schon auf max. 1 Gb erhöht. Das reicht aktuell bei weitem nicht.
 

ARadauer

Top Contributor
1. Einlesen der ersten Logdatei. Dabei werden alle Zeilen, die die Schlüsselworte "Starte Versand..." und "Erhalte Antwort..." enthalten in ein String-Array geschrieben.
wie ließt du ein? Ich würde eine ArrayListe benutzen

PS: Habe den Heapspace schon auf max. 1 Gb erhöht. Das reicht aktuell bei weitem nicht.
wie hast du das gemacht, bist du dir sicher dass du ein GB zur verfügung hast?

Java:
System.out.println("Total Memory"+Runtime.getRuntime().totalMemory());    
       System.out.println("Free Memory"+Runtime.getRuntime().freeMemory());
was kommt da?
 

oetzi

Bekanntes Mitglied
Hi ARadauer,

danke schonmal für deine Antwort!

wie ließt du ein? Ich würde eine ArrayListe benutzen

Sorry, da habe ich mich nicht klar genug ausgedrückt. Ich benutze eine ArrayList<String>


wie hast du das gemacht, bist du dir sicher dass du ein GB zur verfügung hast?

Ich starte das ganze im Moment aus Eclipse mit den Parametern -Xms512m -Xmx1024m und ja, ich war mir schon recht sicher, dass das Gig zur Verfügung steht... Tut es aber wohl doch nicht; siehe unten

Java:
System.out.println("Total Memory"+Runtime.getRuntime().totalMemory());    
       System.out.println("Free Memory"+Runtime.getRuntime().freeMemory());
was kommt da?

mhh, die Ausgabe ist interessant!
Die Zeile hier wird wie gesagt nach jeder bearbeiteten Datei ausgegeben:

Free Memory left in Mb: 418 || Total Memory in Mb: 508
Free Memory left in Mb: 335 || Total Memory in Mb: 508
Free Memory left in Mb: 247 || Total Memory in Mb: 508
Free Memory left in Mb: 161 || Total Memory in Mb: 508
Free Memory left in Mb: 97 || Total Memory in Mb: 508
Free Memory left in Mb: 370 || Total Memory in Mb: 508
Free Memory left in Mb: 297 || Total Memory in Mb: 508
Free Memory left in Mb: 203 || Total Memory in Mb: 508
Free Memory left in Mb: 134 || Total Memory in Mb: 508
Free Memory left in Mb: 63 || Total Memory in Mb: 508 <hier nach flog die HeapSpace Exception beim letzten Durchlauf>
Free Memory left in Mb: 378 || Total Memory in Mb: 508
Free Memory left in Mb: 290 || Total Memory in Mb: 508
...

Ich hatte auch schon bevor ich den "total memory" ausgegeben hatte gesehen, dass nach der 5.-6. Datei auf einmal wieder mehr Speicherplatz zur Verfügung steht, hatte allerdings gedacht, dass dies daran liegt, dass einfach die Grenze von 512 (Xms) auf 1024 (Xmx) erhöht wird.
Aber das scheint ja nicht zu stimmen, da der total Memory gleich bleibt.
Desweiteren läuft das Programm jetzt schon länger als beim letzten Mal.
Kann es sein, dass der garbage collector beim letzten Mal einfach zu langsam war? Wenn ich mich richtig erinnere ist es ja mehr oder weniger zufällig, wann der GC wo aktiv ist. (Hatte übrigens auch mal ein System.gc() eingebaut ohne mir wirklich sicher zu sein, dass das wirklich was bringt)

Auf jedenfall schließe ich aus der Ausgabe des Total Memory, dass ich den Xms Wert wohl besser direkt auf 1024 setze, da ja anscheinend nicht mehr Speicher bei Bedarf geholt wird. Korrekt?

PS: Aktuell läuft das Programm immer noch! Der "Free Memory" wurde jetzt schon zum 3. Mal wieder erhöht. Verstehe ich zwar nicht, aber ich will mich nicht beschweren ;-)
 

oetzi

Bekanntes Mitglied
Kleine Ergänzung:
Die Auswertung ist komplett durch gelaufen.
Das freut mich natürlich auf der einen Seite, auf der anderen Seite befürchte ich ja, dass da vielleicht beim nächsten Lauf wieder die Exception fliegt.

Deswegen wäre ich durchaus noch an Hinweisen interessiert, die mir verraten, warum überhaupt der Speicher aufgebraucht wird. Ist da wirklich einfach der Garbadge Collector zu "langsam" für, oder kann das an was anderem liegen?
 

musiKk

Top Contributor
Hast Du mal durch Profiling festgestellt, wo der Speicher verbraucht wird? Eine einfache Variante ist VisualVM, welches einem anzeigen kann, welche Objekte am häufigsten vorkommen.

Gibt es sonst noch irgendwelche Java-typischen Speicherfallen in die man reintreten kann?

Ist zwar nur eine Anekdote, aber ich bin mal mit [c]String#substring()[/c] reingefallen. Dabei habe ich von sehr großen Strings nur kleine Teile per [c]substring()[/c] ausgeschnitten. Im Hintergrund wird aber das gleiche char-Array verwendet, sodass der Speicher dadurch gleich bleibt.
 

oetzi

Bekanntes Mitglied
@musiKk: danke für den Tipp. Diese Möglichkeit kannte ich noch gar nicht. Scheint mir aber sehr nützlich zu sein!

Habe jetzt mal mein Programm angeworfen und über VisualVM den Profiler gestartet.
ein Char-Array verbraucht schicke 99,8% des Speichers. siehe Anhang.

Aber so wirklich bringt mich das jetzt nicht weiter oder?
Da ich nicht mit char-Arrays arbeite, nehme ich an, dass das irgendeine interne Sache von Java ist. Dabei könnte es sich ja offentlichtlich um die ArrayList<String> handeln, die ich hauptsächlich in meinem Programm verwende.
 

Woodstock

Mitglied
Hallo,

wie liest du denn die Datei ein?

Ich würde es mit 'nem BufferedWriter und dann der ReadLine()-Methode machen. Und falls deine Logdateien nicht aus einer einzelnen Zeile bestehen dürften da kleinere Häppchen Speicher ausreichen...

Das ist mir eh ein bisschen unklar, warum du (anscheinend) die ganze Zeit auf einem riesigen char[] 'rumreitest...

Dabei werden alle Zeilen, die die Schlüsselworte "Starte Versand..." und "Erhalte Antwort..." enthalten in ein String-Array geschrieben.

Ich hoffe, du schreibst "Starte..." und "Erhal..." nicht immer wieder in dein Array?
 

Empire Phoenix

Top Contributor
Hm Strings sind intern doch nchts anderes als chararrays ?

fallen mit strings:

"bla" + "blu" +"bli"
erzeugt für jedes + einen Stringbuilder und eine kopie des cahrarrays
lieber wenn mehr als ein + vorkommt gleich eine stringbuilder nehmen.
 

oetzi

Bekanntes Mitglied
so, jetzt komme ich endlich wieder zu diesem Problem hier.

@woodstock: ja ich benutze einen bufferedReader um per readLine die relevanten Zeilen aus den log-Dateien vor zu selektieren und in die ArrayList<String> zu schreiben. Und ja, ich schreibe die komplette Zeile in die ArrayList.
Wahrscheinlich willst du darauf hinaus, dass das mehr Speicher verbraucht, als wenn ich nur die relevanten Infos per substring extrahieren würde, aber darum geht es ja eigentlich nicht.
Nach der Verarbeitung jeder log-Datei scheinen ja ca. 70Mb Speicher verbraucht zu werden. Diesen Verbrauch könnte ich vielleicht reduzieren, aber das eigentlich Problem wäre damit ja nicht gelöst.
Mir geht es ja darum zu verstehen, warum der belegte Speicher nicht wieder frei gegeben wird, wenn ich per remove die einzelnen Einträge aus der ArrayList wieder lösche.

@Empire Phoenix:
Habe mich jetzt gerade nochmal bei der Javainsel über das Thema schlau gemacht um das besser nachvollziehen zu können.
okay, wenn ich also 2 String mit dem + Operator verbinde, entsteht ein 3. Stringobjekt mit dem Zielstring, aber auch hier würde ich erwarten, dass dann der Speicherplatz der anderen beiden Strings vom Garbage Collector wieder frei gegeben wird.
Oder dauert das im Schnitt einfach so lange bis der GC aktiv wird? Werde mir bei Gelegenheit zu dem Thema GC auch mal weitere Literatur gönnen :)
 

musiKk

Top Contributor
Werde mir bei Gelegenheit zu dem Thema GC auch mal weitere Literatur gönnen :)

Die Zeit kannst Du Dir glaube ich sparen. Auf den GC hast Du innerhalb der JVM keinen Einfluss. Klar gibt es [c]System.gc()[/c], aber das ist so sinnvoll wie ein Kropf. Es wird kein Speicherfehler fliegen, bevor der GC nicht probiert hat, Speicher freizugeben.
Der Speicher kann vom GC freigegeben werden, sobald es keine Referenz mehr darauf gibt. Wenn Du also zwei Strings verkettest und einen dritten erhältst, dann wird der Speicher für die ersten beiden so lange nicht freigegeben, wie sie noch referenziert werden.
 
?

?!?!?

Gast
okay, wenn ich also 2 String mit dem + Operator verbinde, entsteht ein 3. Stringobjekt mit dem Zielstring, aber auch hier würde ich erwarten, dass dann der Speicherplatz der anderen beiden Strings vom Garbage Collector wieder frei gegeben wird.

Ohne dem Garbage Collector explicit zu sagen welcher String zum entfernen bereit ist, ist es unbestimmt wann diese entfernt werden.
Normalerweise sagt man den Garbage Collector bitte die zwei Strings entfernen:

Java:
stringEins = null;
stringZwei = null;
Um der VM mehr Speicher zur Verfügung zu stellen macht man eigentlich:

Java:
String userdir = System.getProperty("user.dir");
        String cmd = "java -Xms512m -Xmx1024m -jar \"" + userdir + "\\App.jar\"";
        try {
            Runtime.getRuntime().exec(cmd);
        } catch (IOException e) {
            // Mach was
        }
        System.exit(0);

Und das sollte eigentlich keine Probleme machen.
 

oetzi

Bekanntes Mitglied
danke für die Infos.
Auch wenn das Thema noch nicht restlos geklärt ist, werde ich es mal als erledigt markieren.
Sonst kann man sich ja noch tagelang darüber unterhalten :)
 
D

DerBesucher

Gast
java hat für Strings einen speziellen Speicherbereich der nicht vom GC überwacht wird. einfach mal googlen
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
V Java heap space Problem Allgemeine Java-Themen 8
V Wieso Heap Space Problem? Allgemeine Java-Themen 14
Y PDF Report mit Tomcat Heap Space Problem Allgemeine Java-Themen 9
kb22 CMS mit großen Dateien (heap problem) Allgemeine Java-Themen 3
V Serialisierungsproblem bzw. Heap Problem Allgemeine Java-Themen 13
N Speicher Problem bei grossem Heap Allgemeine Java-Themen 15
krgewb Problem mit Umlauten und Eszett bei InputStream Allgemeine Java-Themen 3
Max246Sch Backtracking Problem Box Filler Allgemeine Java-Themen 6
NightVision402 VisualVM Startskript Problem Allgemeine Java-Themen 3
javaBoon86 Email Server Connection Problem Allgemeine Java-Themen 1
F Problem mit PDFBOX Library Allgemeine Java-Themen 1
A Java modul Problem Allgemeine Java-Themen 4
D Read JSON File Problem Allgemeine Java-Themen 9
urmelausdemeis Exception in thread "main" java.lang.Error: Unresolved compilation problem: Allgemeine Java-Themen 7
J Problem mit JasperReports Allgemeine Java-Themen 8
M log4j Problem mit jlink Allgemeine Java-Themen 19
8u3631984 Problem beim Mocken von Record Klassen Allgemeine Java-Themen 4
torresbig Website login Problem - Jsoup, wie bisher, klappt nicht! Allgemeine Java-Themen 31
P Selenium . getText Problem Allgemeine Java-Themen 9
A Jar zu Exe Problem Allgemeine Java-Themen 13
sserio Variablen Liste erstellt und ein Problem mit dem Index Allgemeine Java-Themen 6
S Folgendes Problem bei einem Programm Allgemeine Java-Themen 1
stormyark Problem beim Klassen erstellen Allgemeine Java-Themen 1
A Thread.sleep Problem Allgemeine Java-Themen 2
A Problem bei der Nachbarschafttest Allgemeine Java-Themen 11
Splayfer Problem: no main manifest attribute Allgemeine Java-Themen 3
G javamail Problem beim Empfangen von Nachrichten Allgemeine Java-Themen 3
Splayfer JDA Problem mit MessageCounter Allgemeine Java-Themen 0
Splayfer Problem mit BufferedWriter Allgemeine Java-Themen 3
F Streams als Alternative für dieses Problem ? Allgemeine Java-Themen 15
N Maven Problem mit Datenbanktreiber (H2 Embedded) Allgemeine Java-Themen 12
T Problem beim Umwandeln in eine Jar-Datei Allgemeine Java-Themen 3
B Einfach Elemente zweier Arraylisten kreuz und quer vergleichen, min und max Problem? Allgemeine Java-Themen 16
C ArrayList Problem Allgemeine Java-Themen 3
kev34 nim-Spiel problem Allgemeine Java-Themen 1
D Firebase retrieve data Problem, Child Element wird nicht angesprochen Allgemeine Java-Themen 0
G Welches Problem besteht bei den Typparametern? Allgemeine Java-Themen 5
temi Problem mit Aufrufreihenfolge bei Vererbung Allgemeine Java-Themen 3
Sumo_ow "ArrayIndexOutofBoundsException: 2" Array Problem Allgemeine Java-Themen 6
T PIM basierend auf netbeans via AnyDesk Problem Allgemeine Java-Themen 3
xGh0st2014 Problem mit Java Array Allgemeine Java-Themen 1
Kirby.exe Verständnis Problem bei Rucksack Problem Allgemeine Java-Themen 6
B Eclipse-Lombok-Problem Allgemeine Java-Themen 19
I Input/Output ObjectOutputStream - Problem Allgemeine Java-Themen 7
1 Multiple Choice Knapsack- Problem Allgemeine Java-Themen 2
kodela Problem mit strukturiertem Array Allgemeine Java-Themen 18
E Problem mit Gridlayout und Button Allgemeine Java-Themen 2
A Array Problem Allgemeine Java-Themen 8
bueseb84 Problem Allgemeine Java-Themen 0
S Problem mit Arrays Allgemeine Java-Themen 1
D Nullpointer Exception Problem Allgemeine Java-Themen 5
B Problem mit meinen Klassen Allgemeine Java-Themen 6
A HashMap Methode "get()"-Problem Allgemeine Java-Themen 28
J Problem beim Umstellen auf Java jdk 13 Allgemeine Java-Themen 3
J Problem bei Install java 13 Allgemeine Java-Themen 3
X Profitable Reise Problem Allgemeine Java-Themen 32
A Problem beim öffnen von Java-Installern Allgemeine Java-Themen 1
Dann07 Problem mit JavaMail API Allgemeine Java-Themen 26
J Problem beim Generischen Klassen und Interfaces Allgemeine Java-Themen 2
L Klassen Algorithmus für das folgende Problem entwickeln? Allgemeine Java-Themen 30
J Clear-Problem Allgemeine Java-Themen 10
B Problem zu einem Java Projekt Allgemeine Java-Themen 6
S JFileChooser Problem Allgemeine Java-Themen 4
M Traveling Salesman - MST Heuristik Problem Allgemeine Java-Themen 4
J Traveling Salesman Problem Allgemeine Java-Themen 14
E Java Editor Problem mit 2er Exceptions Allgemeine Java-Themen 12
C code oder Bibliotheken für 2-Center Problem Allgemeine Java-Themen 4
M Salesman Problem - Bruteforce Algorithmus Allgemeine Java-Themen 23
S Methoden Problem mit NullPointerException Allgemeine Java-Themen 9
Javafan02 Problem mit if-clause Allgemeine Java-Themen 17
J Lombok Problem mit Konstruktoren bei Verberbung Allgemeine Java-Themen 1
kodela Event Handling Problem mit der Alt-Taste Allgemeine Java-Themen 16
W Threads Problem Allgemeine Java-Themen 15
D (Verständnis-)Problem mit Unterklasse Allgemeine Java-Themen 4
S Problem mit Generic bei unmodifiableCollection Allgemeine Java-Themen 4
S jserialcomm Problem Allgemeine Java-Themen 1
Flynn Thread-Problem... Allgemeine Java-Themen 2
J Generische Interface - Problem Allgemeine Java-Themen 3
G Problem beim GUI Allgemeine Java-Themen 9
L Applet Problem "security: Trusted libraries list file not found" ? Allgemeine Java-Themen 7
A OOP Problem beim Berechnen der größten Fläche eines Ringes Allgemeine Java-Themen 19
T Problem mit externen Datenbankzugriff über SSH Tunnel Allgemeine Java-Themen 4
F Problem beim Einlesen einer Textdatei Allgemeine Java-Themen 12
S Java OpenOffice Problem mit Windows-Benutzerwechsel Allgemeine Java-Themen 19
K Threads RAM Problem Allgemeine Java-Themen 20
P Operatoren Problem mit Zähler in recursiver Schleife Allgemeine Java-Themen 2
C Int Problem Allgemeine Java-Themen 8
C J2V8 NodeJs Java Bride Problem und Frage!?!? Allgemeine Java-Themen 1
J Problem bei Hashmap Key-Abfrage Allgemeine Java-Themen 4
C Webseiten Programm problem Allgemeine Java-Themen 5
M LocalDate Problem Allgemeine Java-Themen 4
J "Problem Objektorientierung" Allgemeine Java-Themen 20
geekex Problem Meldung! Was tun?! Allgemeine Java-Themen 19
T Klassen Override Problem Allgemeine Java-Themen 7
L Unbekanntes Problem Allgemeine Java-Themen 1
FrittenFritze Problem mit einer JComboBox, Event temporär deaktivieren Allgemeine Java-Themen 11
Blender3D Java Swing Programm Windows 10 Autostart Problem Allgemeine Java-Themen 2
F HTTPS Zertifikat Problem Allgemeine Java-Themen 3
M OpenCV KNearest Problem Allgemeine Java-Themen 0
Tommy Nightmare Project Euler: Problem 22 Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben