Hi!
Anscheinend habe ich die Speicherbenutzung von JAVA noch nicht richtig verstanden, da ich in bestimmten Faellen eine "java.lang.OutOfMemoryError: Java heap space"-Fehlermeldung bekomme.
Mein Programm soll Folgendes machen:
Es liest eine bestimmte Anzahl von Namen aus einer Datenbank und schreibt diese Zeilenweise in eine Datei. Danach liest es die neu erstellte Datei zeilenweise ein, holt fuer den entsprechenden Namen am Anfang der Zeile die dazugehoerigen Ergebnisse aus einer bestimmten Ergebnistabelle, fuegt diese der Zeile an und schreibt diese Zeile dann jeweils in eine neue Datei. Dieser Prozess wird in einer for-Schleife fuer mehrere Ergebnistabellen wiederholt. Hier der (gekuerzte) Code (ist schon stark durcheinander, da ich wild rumprobiert habe und die Testausgaben, die ich mir gemacht habe, habe ich auch dringelassen):
Ich hoffe, ich habe alles wichtige hier drin!
Der JVM gebe ich -Xmx1024m mit!
Lasse ich das Programm fuer 500 Sequenzen (Namen) laufen -> klappt's!
2000 -> klappt auch!
Lasse ich das Programm fuer etwas ueber 9000 Sequenzen laufen, bekomme ich folgende Ausgabe (auch gekuerzt):
Wie Ihr seht schein der speicherfressende Teil in der while-Schleife zu sein. Jedoch dachte ich eigentlich, dass ich alle benutzten Objekte, Arrays und Variablen immer wieder "null" setze und der Speicher dadurch immer wieder frei werden sollte. Das scheint irgendwie nicht der Fall zu sein. Nach jeder While-Schleife ist die Speichernutzung deutlich erhoeht und wird leider nicht wieder erniedrigt. Ich habe auch zu Anfang jedes for-Loops (und auch zwischendurch manchmal_ den GC laufen lassen, aber leider hat das ueberhaupt nichts gebracht. Das inTmp-File ist bei Programmabruch 33MB gross und das outFile, in das er gerade schreibt, ist bei Abbruch immer 14MB gross. Aus der 1. Tabelle zieht er eine Spalte, aus der 2. 16, aus der 3. 64, aus der 4. 256 und aus der 5. Tabelle 1024 Spalten. In allen Tabellen und Spalten habe ich kurze Strings.
Koennt Ihr mir helfen und sagen, was ich falsch verstehe und warum der Speicher nicht wieder frei gegeben wird? Seht Ihr den Fehler (in der while-Schleife)? Warum blaeht er sich in der while-Schleife so dermassen auf, obwohl ich alles Zeilenweise mache und manches "null" setze. Und wieso gibt er nach der while-Schleife den Speicher nicht wieder her, obwohl ich auch da eigentlich alles auf "null" setze? Was verstehe ich da nicht richtig bei der Speichernutzung?[/list][/code]
Anscheinend habe ich die Speicherbenutzung von JAVA noch nicht richtig verstanden, da ich in bestimmten Faellen eine "java.lang.OutOfMemoryError: Java heap space"-Fehlermeldung bekomme.
Mein Programm soll Folgendes machen:
Es liest eine bestimmte Anzahl von Namen aus einer Datenbank und schreibt diese Zeilenweise in eine Datei. Danach liest es die neu erstellte Datei zeilenweise ein, holt fuer den entsprechenden Namen am Anfang der Zeile die dazugehoerigen Ergebnisse aus einer bestimmten Ergebnistabelle, fuegt diese der Zeile an und schreibt diese Zeile dann jeweils in eine neue Datei. Dieser Prozess wird in einer for-Schleife fuer mehrere Ergebnistabellen wiederholt. Hier der (gekuerzte) Code (ist schon stark durcheinander, da ich wild rumprobiert habe und die Testausgaben, die ich mir gemacht habe, habe ich auch dringelassen):
Code:
"File mit Namen (inFile) wurde erzeugt!"
"for each toolID" (gekuerzt){
...
System.out.println("beforeMd: "+((Runtime.getRuntime().totalMemory() -
Runtime.getRuntime().freeMemory())/1024) + " von " +
(Runtime.getRuntime().totalMemory()/1024));
String[] md = ds.get_MetaClustMetaData(toolID, wlCGR);
if (md!=null) {
numberOfColumns = md.length;
logr.debug("Reading tmpFile and adding to each line " +
"the corresponding result line of the tool " +
"with the id: "+toolID);
//read the old file and write it + the new data
//in a new file
try {
System.out.println("beforeFrBr: "+((Runtime.getRuntime().totalMemory() -
Runtime.getRuntime().freeMemory())/1024) + " von " +
(Runtime.getRuntime().totalMemory()/1024));
br = new BufferedReader(new FileReader(inFile));
fw = new BufferedWriter(new FileWriter(outTmpFile));
System.out.println("createdBrFr: "+((Runtime.getRuntime().totalMemory() -
Runtime.getRuntime().freeMemory())/1024) + " von " +
(Runtime.getRuntime().totalMemory()/1024));
// write the MetaData line first
line = br.readLine();
s = new StringBuilder(100000);
s.append(line);
for (int j=0; j<numberOfColumns; j++) {
s.append("\t").append(md[j]);
}
s.append(lineSep);
fw.write(s.toString());
fw.flush();
md = null;
System.out.println("mdNull: "+((Runtime.getRuntime().totalMemory() -
Runtime.getRuntime().freeMemory())/1024) + " von " +
(Runtime.getRuntime().totalMemory()/1024));
// s = null; //NEW
seqIdx = 0;
s.replace(0, s.length(), "");
// now write the results of the module for
// each sequence
System.out.println("Gehe jetzt in while-Schleife!");
//------------in dieser while-Schleife wird die Speichernutzung aufgeblaeht-----------------------------
while ((line = br.readLine()) != null) {
s.append(line);
tmp = ds.get_MetaClustResults(toolID,
seqSet.getSequenceIdAt(seqIdx),
wlCGR);
for (int j=0; j<numberOfColumns; j++) {
s.append("\t").append(tmp[j]);
}
s.append(lineSep);
fw.write(s.toString());
fw.flush();
tmp = null;
s.replace(0, s.length(), "");
// s = null; //NEW
seqIdx++;
}
System.out.println("Bin aus while-Schleife raus!");
System.out.println("ausW: "+((Runtime.getRuntime().totalMemory() -
Runtime.getRuntime().freeMemory())/1024) + " von " +
(Runtime.getRuntime().totalMemory()/1024));
if (seqIdx+1!=numberOfRows) {
logr.fatal("Different numbers of rows!");
System.exit(28);
}
}
catch ( IOException e ) {
logr.fatal("Couldn't create outTmpFile: " +
outTmpFile);
System.exit(29);
}
finally {
try {
if (fw != null) fw.close();
if (br != null) br.close();
}
catch (IOException e) {
logr.error("Couldn't close outTmpFile: " +
outTmpFile);
//System.exit(30);
}
}
fw = null;
br = null;
System.out.println("fwBrNull: "+((Runtime.getRuntime().totalMemory() -
Runtime.getRuntime().freeMemory())/1024) + " von " +
(Runtime.getRuntime().totalMemory()/1024));
//delete the old file
File f = new File(inFile);
f.delete();
logr.debug("Rename the new tmpFile into the old " +
"tmpFile.");
File cp = new File(outTmpFile);
copied = cp.renameTo(new File(inFile));
if (!copied) {
logr.fatal("Couldn't copy the file to the " +
"new filename!");
System.exit(39);
}
}
else {
logr.fatal("MetaData result set is empty!");
System.exit(37);
}
}
...
Der JVM gebe ich -Xmx1024m mit!
Lasse ich das Programm fuer 500 Sequenzen (Namen) laufen -> klappt's!
2000 -> klappt auch!
Lasse ich das Programm fuer etwas ueber 9000 Sequenzen laufen, bekomme ich folgende Ausgabe (auch gekuerzt):
371 [main] DEBUG metaclust.Clusterer - Getting all sequence names...
1764 [main] DEBUG metaclust.Clusterer - Writing tmpFile with sequence names...
1939 [main] DEBUG metaclust.Clusterer - Finished writing the sequence names into the tmpFile.
1941 [main] DEBUG metaclust.Clusterer - Starting for-loop over the tool ids...
forLoop: 4364 von 9016
beforeMd: 4364 von 9016
1984 [main] DEBUG metaclust.Clusterer - Reading tmpFile and adding to each line the corresponding result line of the tool with the id: 1
beforeFrBr: 4364 von 9016
createdBrFr: 4404 von 9016
mdNull: 4611 von 9016
Gehe jetzt in while-Schleife!
Bin aus while-Schleife raus!
ausW: 14254 von 15124
fwBrNull: 14254 von 15124
3167 [main] DEBUG metaclust.Clusterer - Rename the new tmpFile into the old tmpFile.
forLoop: 13841 von 24808
beforeMd: 13841 von 24808
3254 [main] DEBUG metaclust.Clusterer - Reading tmpFile and adding to each line the corresponding result line of the tool with the id: 2
beforeFrBr: 13841 von 24808
createdBrFr: 13873 von 24808
mdNull: 14069 von 24808
Gehe jetzt in while-Schleife!
Bin aus while-Schleife raus!
ausW: 55885 von 69956
fwBrNull: 55885 von 69956
5433 [main] DEBUG metaclust.Clusterer - Rename the new tmpFile into the old tmpFile.
forLoop: 55374 von 98992
beforeMd: 55374 von 98992
5668 [main] DEBUG metaclust.Clusterer - Reading tmpFile and adding to each line the corresponding result line of the tool with the id: 3
beforeFrBr: 55374 von 98992
createdBrFr: 55374 von 98992
mdNull: 55569 von 98992
Gehe jetzt in while-Schleife!
Bin aus while-Schleife raus!
ausW: 205076 von 285980
fwBrNull: 205076 von 285980
11220 [main] DEBUG metaclust.Clusterer - Rename the new tmpFile into the old tmpFile.
forLoop: 197573 von 353240
beforeMd: 197573 von 353240
11916 [main] DEBUG metaclust.Clusterer - Reading tmpFile and adding to each line the corresponding result line of the tool with the id: 4
beforeFrBr: 197573 von 353240
createdBrFr: 197573 von 353240
mdNull: 197573 von 353240
Gehe jetzt in while-Schleife!
Bin aus while-Schleife raus!
ausW: 777539 von 1012480
fwBrNull: 777539 von 1012480
29302 [main] DEBUG metaclust.Clusterer - Rename the new tmpFile into the old tmpFile.
forLoop: 764902 von 1040512
beforeMd: 764902 von 1040512
32650 [main] DEBUG metaclust.Clusterer - Reading tmpFile and adding to each line the corresponding result line of the tool with the id: 5
beforeFrBr: 764902 von 1040512
createdBrFr: 764902 von 1040512
mdNull: 764902 von 1040512
Gehe jetzt in while-Schleife!
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Wie Ihr seht schein der speicherfressende Teil in der while-Schleife zu sein. Jedoch dachte ich eigentlich, dass ich alle benutzten Objekte, Arrays und Variablen immer wieder "null" setze und der Speicher dadurch immer wieder frei werden sollte. Das scheint irgendwie nicht der Fall zu sein. Nach jeder While-Schleife ist die Speichernutzung deutlich erhoeht und wird leider nicht wieder erniedrigt. Ich habe auch zu Anfang jedes for-Loops (und auch zwischendurch manchmal_ den GC laufen lassen, aber leider hat das ueberhaupt nichts gebracht. Das inTmp-File ist bei Programmabruch 33MB gross und das outFile, in das er gerade schreibt, ist bei Abbruch immer 14MB gross. Aus der 1. Tabelle zieht er eine Spalte, aus der 2. 16, aus der 3. 64, aus der 4. 256 und aus der 5. Tabelle 1024 Spalten. In allen Tabellen und Spalten habe ich kurze Strings.
Koennt Ihr mir helfen und sagen, was ich falsch verstehe und warum der Speicher nicht wieder frei gegeben wird? Seht Ihr den Fehler (in der while-Schleife)? Warum blaeht er sich in der while-Schleife so dermassen auf, obwohl ich alles Zeilenweise mache und manches "null" setze. Und wieso gibt er nach der while-Schleife den Speicher nicht wieder her, obwohl ich auch da eigentlich alles auf "null" setze? Was verstehe ich da nicht richtig bei der Speichernutzung?[/list][/code]