# Tomcat VM out of memory



## Henry (6. Jan 2008)

Hallo,

ich führe immer wieder eine umfangreiche Berechnung in Tomcat durch. Unter anderem wird auch viel in eine Datenbank geschrieben. Nun habe ich das Problem, dass häufig, nachdem ich 3 - 4 Mal diese Berechnung durchführe, eine "out-of-memory" Exception kommt. Wenn ich die Speichergröße der VM erhöhe, funktioniert es wieder in bißchen länger. 

Meine Frage ist, wie kann ich den Speicher zwischen den einzelnen Berechnungen leeren, denn jede Berechnung einzeln ist kein Problem?

Schonmal vielen Dank.

Tschüß Henry


----------



## HLX (6. Jan 2008)

Das hat mit dem Tomcat nichts zu tun sondern liegt direkt an deinem Programm. Du musst überflüssige Objekte freigeben, so dass der Garbage Collector diese entfernen kann. So lange noch Referenzen auf diese Objekte bestehen können sie auch nicht entfernt werden. Weiß ja keiner ob du die nochmal brauchst.


----------



## maki (6. Jan 2008)

PermSize erhöhen kann auch helfen, genaues findest du nur mit jconsole raus, ab Java 5.


----------



## PollerJava (7. Jan 2008)

Ich würd da vorsichtig sein, ich hatte auch so ein Problem,
Wenn du eine HashMap oder eine Liste verwendest, dann musst du die Referenzen auf die Objekte in der Liste oder der Map explixit löschen, diese werden nämlich nicht automatisch vom gc gelöscht, also einfach die nicht mehr benötigten Instanzen in der Map auf "null" setzen,
ansonsten kannst Du z.B. mit dem Profiler von NetBeans oder Eclipse schauen, wer dir da denn Speicher so anfüllt,
(Profiler is bei NetBeans6.0 standardmäßig dabei)

 PS: PermSize erhöhen hilft ja nur, wenn dein Programm sauber programmiert ist und keine Speicher-Löcher entstehen und das müssten schon wilde berechnungen sein, wenn Du mit der Standardgröße nicht auskommen solltest.


----------



## Henry (7. Jan 2008)

Hallo vielen Dank schonmal für die Antworten!

Leider kann ich mit dem "überflüssige Objekte freigeben" nicht so viel anfagen? Soll ich nicht mehr benötigte Variablen und Referenzen auf Objekte null setzen wie z. B. bei Visual Basic? Ich dachte das würde der GC automatisch übernehmen?
Ich arbeite mit Eclipse. Wie gesagt, dass Programm läuft innerhalb von Tomcat. Kann solch ein Profiler auch innerhalb vom Tomcat mein Programm analysieren. Was gibt es für Profiler?


Ich erkläre vielleicht nochmal was ich mache:

Also ich habe geographische Koordinaten in Form eines ASCII - Rasters (1200 x 1200 Pixel). Aus diesem lese ich die sinnvollen Werte (über 0) aus, wandele Sie in eine andere Projektion um und speichere dann die Werte in eine Datenbank Tabelle.

Nachfolgend nochmal im Einzelnen was ich mache:
- Ich nehme zuerst ein Array gezippter ASCII Dateien von einem Webservice entgegen.
- Jede dieser ASCII Dateien wird entzippt. Eine ASCII Datei ist dabei ungezippt 16MB groß.
- Ich lese die sinnvollen Werte dann aus jeder der ASCII Dateien aus und schreibe sie in die Datenbank.
- Dannach schreibe ich noch eine XML Datei, eine SLD (Styled Layer Descriptor) Datei und starte meinen Mapserver mittels einer GET - Anfrage neu.

Ich denke er harkt vor allem bei bei dem entzippen der ASCII Dateinen. Ich hänge deswegen den Code dieser Methode mal ran.


Vielleich hat hat jemand eine Idee, an was bei dieser Methode nicht so stimmt?


```
/**
	 * Damit werden die Byte-Ströme innerhalb des GeoData - Arrays entzippt.
	 * @param GeoDataArray
	 * @return GeoData Array ungezippt.
	 * @throws IOException
	 */
	public GeoData[] unzip (GeoData[] GeoDataArray) throws IOException
	{
		 byte[] buffer = new byte[16384];
		 
		for (int i = 0; i < GeoDataArray.length; i++) 
		{
			GeoDataFile[] GeoDataFileArray = GeoDataArray[i].getLayerFiles();
			
		 	for (int j = 0; j < GeoDataFileArray.length; j++) 
	    	{
				this.ID = HardCoded.VOR_ID + "_" + GeoDataFileArray[j].getDateiname().substring(0, GeoDataFileArray[j].getDateiname().lastIndexOf("_"));

	    		byte[] datenZipped = GeoDataFileArray[j].getDateiinhalt().clone();
	    		
	    		int value;
	    	    ZipInputStream inputStream = new ZipInputStream(new ByteArrayInputStream(datenZipped));
	    	    ByteArrayOutputStream bos = new ByteArrayOutputStream();
	    	    
				ZipEntry entry = inputStream.getNextEntry();
				/*while((value = inputStream.read()) != -1)
			    {
			    	bos.write(value);
			    }*/
				while((value = inputStream.read(buffer)) > 0)
		        {
		            bos.write(buffer, 0, value);
		         }
			    
			    bos.close();
			    inputStream.close();
			    
			    byte[] datenUnzipped = bos.toByteArray();
			    
			    GeoDataFileArray[j].setDateiinhalt(datenUnzipped);
			}
		 	
		 	GeoDataArray[i].setLayerFiles(GeoDataFileArray);
		}
   
    	return GeoDataArray;
	}
```


----------



## Henry (9. Jan 2008)

Keiner sonst eine Idee?


----------



## Angel4585 (10. Jan 2008)

Also du erzeugst bei dem Aufruf dieser Methode ein Array mit 16K Elementen. Was machst du dann mit dem Array? Versuch das Array (buffer) man null zu setzen am Ende..

Obwohl.. eigentlich isses ne lokale Variable, sollte doch der gc übernehmen.


----------



## maki (10. Jan 2008)

> Henry


Was sagt Lambda Probe bzw. JConsole?


----------

