Problemlösungvorschläge zum beliebten Java Fehler : java.lang.OutOfMemoryError:

IzYaBoi

Grünschnabel
Gute Morgen liebe Tutorialgemeinde,

ich möchte im folgenden Beitrag kurz auf meine Projekt eingehen an dem ich programmiere und was für Fehler dabei enstehen. Würde mich über Lösungen oder Ansatzhilfen freuen.

Zunächst möchte ich erwähnen das ich Server+CLient+Datenbank(MYSQL 5.0.22 ) Seitig arbeite also nach dem 3 Schicht Modell mit dem Jboss Server 1.4.0.2. Soviel sei nur dazu gesagt. Sollte eigentlich unrelevant zum folgenden Fehler sein:

Das Tool an dem ich arbeit ist ein Exporttool das anhand von gesetzter Filter eine Textdatei erstellen soll mit fest definierter Satzlänge. Soweit so gut, auf meiner CLientseite gibt es folgende Methode die Aufgerufen wird wenn der benutzer seine Filter gesetzt hat und auf erstellen geklickt hat:

Code:
public void erstelleAusgabeDatei() {
		
		try {
			//Erstellung eines FileWriters und BufferedWriter                        
                       ausgabeWriter = new FileWriter(ausgabeDatei); 
			ausgabeBuff = new BufferedWriter(ausgabeWriter);
			
		      // "daten" vom Datentyp ARRAY ist eine Instanz meine DTO Objekts
                     // instanceMzaw10Facade.Holen_MZAW10_Export ist eine Servermethode die anhand folgender Parameter die gewünschte Menge holt

                      daten = instanceMzaw10Facade.Holen_MZAW10_Export(
					this.monathaelftenvon, this.monathaelftenbis,
					this.IDErhebung, this.Aland);
	//REST SELBSTERKLÄREND	
                 AnzahlDatensaetze = daten.length;
			
                       if (daten != null) {	

				for (int i = 0; i < daten.length; i++) {

					String EF10  = daten[i].getB_ef10();
					
					if (EF10.length() < 15) {
						int differenz = 15 - EF10.length();
						for (int j = 0; j < differenz; j++) {
							EF10 += " ";
						}
					}
					
				....
					
                            //	Zum Schluss setze ich die Abgefragten Felder zu einen String  zusammen und schreibe diese in eine Datei.				

				        String datensatz = EF10 + usw ...
                                        ausgabeBuff.write(this.datensatz);
					ausgabeBuff.newLine();
				}

			} else {
				JOptionPane.showMessageDialog(null, "Keine Sätze vorhanden");
			}
			ausgabeWriter.close();	
			ausgabeBuff.close();
		} catch (Exception e) {
			System.out.println(e + "Fehler beim Erstellen der Ausgabedatei");
		}
		
	}

Das Problem ist nun das ich diesen Fehler bei einer Anzahl >= 5000 bekomme : Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space


Habe schon versucht den Heap Space mit -Xmx256 zu erhöhen aber das erscheint mir keine Dauerhafte Lösung bei so einer geringen Anzahl von Sätzen. Zudem dies ne zeit Funktioniert hat bei ungefähr 13.000 Sätzen aber nun auch nix bringt. Zugriffzeit von minimalen 26 sek und max über 30 Oo was mir schon sehr viel erscheint.

Würde mich freuen wenn ihr irgendein Hinweis auf eine Lösung habt. :)
 
Zuletzt bearbeitet:
Hallo,

ich würde an deiner Stelle erstmal versuchen nicht alles in einen riesen Buffer zu laden sondern alle Paar X Sätze ein "Häppchen" in die Ausgabe zu schreiben.

Weiterhin solltest du eher einen StringBuilder verwenden und Strings nicht per s+="" verknüpfen.

Ansonsten kann man dazu nicht viel sagen (nur dass eure Methodenbenennungskonventionen ziemlich Fragwürdig sind)

Gruß Tom
 
von den Methodenbenennungskonventionen wollen wir jetzt mal nicht sprechen da weiß is selbst das die nicht vernüftig sind aber die Serverseite programier ich nicht und da meine Firma alles in deutsch bennennt setze ich das nur so fort. =) aber das spiel keine Rolle.

ok die Strings mit nem stringbuilder per append zu verknüpfen werde ich mal machen.

aber was meinst du mit häppchen? du meinst ich soll mir aus meinen array nur ne bestimmte anzahl rausholen. diese mit write in die textdaetei schreibe diese mit close schließen und dann da ganze noch mal ausführen in einer schleife?
 
Gemeint war:

Im Moment baust du dir einen riesen String und schreibst ihn dann in deinen Stream.
Stattdessen wäre es wahrscheinlich klüger die Strings, statt sie erst zu einem RIESIGEN zu verbinden direkt in der Schleife einzeln in den Stream zu schicken. Also Häppchenweise.
Das spart dir den riesen Alloc.
 
ich hab jetzt mal alles nochmal auskommentiert.

Java:
public void erstelleAusgabeDaei() {
		
		try {
			
			daten = instanceMzaw10Facade.Holen_MZAW10_Export(
					this.monathaelftenvon, this.monathaelftenbis,
					this.IDErhebung, this.Aland);
			
		System.out.println("test");
		}catch (Exception e) {
			System.out.println("Fehler beim Erstellen der Ausgabedatei" +e);
		}
	
	}

nix sinnvolles aber wollt nur mal schaun ob nun noch mal die Fehlermeldung kommt. und nun weiß ich echt nciht warum . bei mehr als 5295 datensätze in meinem array die ich durhc meine Holen methode aufd em server hole Oo siehe oben bekomm ich den fehler :confused: wollte nur teste ob es über haupt beim erstellen noch zu ausgabe kommt ;/ was ist das los ? keine catch exception nur dieser java.lang.OutOfMemoryError: Java heap space fehler

kann es sein das es im zu viel ist wenn er diese result menge von 5295 ins Array kopiert Oo
 
Zuletzt bearbeitet von einem Moderator:
Der Clientcode nützt uns herzlich wenig. Das Memoryleak ist wohl in dieser kryptischen Methode (zu den nichtssagenden Namen hat Tom ja schon was gesagt). Wenn man sich nur halbwegs mit den Grundlagen von Java auskennt ist auch klar, dass ein catch (Exception ex) keinen OutOfMemoryError fangen kann. Was willst du auch machen, wenn kein Speicher mehr da ist? Es ist schlicht und einfach ein Bug ;).

Wenn der Code dieser obskuren Methode allerdings genauso ausschaut, wie der oben, werden sicherlich wenige Teilnehmer hier Lust haben sich das anzuschauen ;).

REINHAUN!
 
ich müsste nochmal klarstellen :


diese kryptischen Methode ist wie folgt auf der server seite in einer sessionbean geschrieben:
Der SQL String zum aufruf ist folgendermaßen deklariert.

String sqlexportmzaw10 = "{ call spmzExportMzaw10(?,?,?,?) }";

Code:
private void prepareprocexportmzaw10() throws SQLException
		{
			db.con = m_dataSource.getConnection();
			s_logger.log(Level.INFO,"about to execute" + sqlexportmzaw10);
			db.callstmt = db.con.prepareCall(sqlexportmzaw10);
			db.callstmt.setString(1,this.monhaelfte);
			db.callstmt.setString(2,this.monhaelftebis);
			db.callstmt.setInt(3,this.erhebung);
			db.callstmt.setString(4,this.land);
		}

Code:
 /**
		 * Business method
		 * @ejb.interface-method  view-type = "remote"
		 */
	 
	 public MZAW10Export[] Holen_MZAW10_Export(String monathaelfte , String monathaelftebis,int erheb, String awbland){
	 	
	 	MZAW10Export[] result = null;
	 	
	 	this.monhaelfte = monathaelfte;
	 	this.monhaelftebis = monathaelftebis;
	 	this.erhebung = erheb;
	 	this.land = awbland;
	 	
		db = new DbResourceHolder();
	 	
		try {
	 		prepareprocexportmzaw10();
	 		db.res = db.callstmt.executeQuery();
	 		//Positionierung auf den letzten Satz und Abfrage der Zeilen
			db.res.last();
			int zeilen = db.res.getRow();
			if (zeilen > 0) {
			// Erneute Positionierung auf den ersten Satz
			db.res.first();
           result = new MZAW10Export[zeilen];         
			int i = 0;
			while (i < zeilen) {
				result[i] = new MZAW10Export();
				result[i].setB_ef1(db.res.getString("EF1"));
				result[i].setB_ef2(db.res.getString("EF2"));
				result[i].setB_ef3(db.res.getString("EF3"));
				result[i].setB_ef4(db.res.getString("EF4"));
				result[i].setB_ef5(db.res.getString("EF5"));
				result[i].setB_ef6(db.res.getString("EF6"));
				result[i].setB_ef7(db.res.getString("EF7"));
				result[i].setB_ef8(db.res.getString("EF8"));
				result[i].setB_ef10(db.res.getString("EF10"));
				result[i].setB_ef11(db.res.getString("EF11"));
				result[i].setB_ef12(db.res.getString("EF12"));
				result[i].setB_ef13u1(db.res.getString("EF13U1"));
				result[i].setB_ef13u2(db.res.getString("EF13U2"));
				result[i].setB_ef15(db.res.getString("EF15"));
				result[i].setB_ef30(db.res.getString("EF30"));
				result[i].setB_ef31(db.res.getString("EF31"));
				result[i].setB_ef32(db.res.getString("EF32"));
				result[i].setB_ef33(db.res.getString("EF33"));
				result[i].setB_ef34(db.res.getString("EF34"));
				result[i].setB_ef36(db.res.getString("EF36"));
				result[i].setB_ef40(db.res.getString("EF40"));
				result[i].setB_ef42(db.res.getString("EF42"));
				result[i].setB_ef50(db.res.getString("EF50"));
				result[i].setB_ef60(db.res.getString("EF60"));
				result[i].setB_ef65(db.res.getString("EF65"));
				result[i].setB_ef100(db.res.getString("EF100"));
				result[i].setB_ef101(db.res.getString("EF101"));
				result[i].setB_ef102(db.res.getString("EF102"));
				result[i].setB_ef103(db.res.getString("EF103"));
				result[i].setB_ef104(db.res.getString("EF104"));
				result[i].setB_ef105(db.res.getString("EF105"));
				result[i].setB_ef106(db.res.getString("EF106"));
				result[i].setB_ef107u1(db.res.getString("EF107U1"));
				result[i].setB_ef107u2(db.res.getString("EF107U2"));
				result[i].setB_ef107u3(db.res.getString("EF107U3"));
				result[i].setB_ef108(db.res.getString("EF108"));
				result[i].setB_ef109(db.res.getString("EF109"));
				result[i].setB_ef110(db.res.getString("EF110"));
				result[i].setB_ef111(db.res.getString("EF111"));
				result[i].setB_ef112(db.res.getString("EF112"));
				result[i].setB_ef113(db.res.getString("EF113"));
				result[i].setB_ef114(db.res.getString("EF114"));
				result[i].setB_ef115(db.res.getString("EF115"));
				result[i].setB_ef116(db.res.getString("EF116"));
				result[i].setB_ef117(db.res.getString("EF117"));
				result[i].setB_ef118(db.res.getString("EF118"));
				result[i].setB_ef119(db.res.getString("EF119"));
				result[i].setB_ef120(db.res.getString("EF120"));
				result[i].setB_ef121(db.res.getString("EF121"));
				result[i].setB_ef122(db.res.getString("EF122"));
				result[i].setB_ef123(db.res.getString("EF123"));
				result[i].setB_ef200(db.res.getString("EF200"));
				result[i].setB_ef201(db.res.getString("EF201"));
				result[i].setB_ef202(db.res.getString("EF202"));
				result[i].setB_ef203(db.res.getString("EF203"));
				result[i].setB_ef204(db.res.getString("EF204"));
				result[i].setB_ef205(db.res.getString("EF205"));
				result[i].setB_ef206(db.res.getString("EF206"));
				result[i].setB_ef207u1(db.res.getString("EF207U1"));
				result[i].setB_ef207u2(db.res.getString("EF207U2"));
				result[i].setB_ef207u3(db.res.getString("EF207U3"));
				result[i].setB_ef208(db.res.getString("EF208"));
				result[i].setB_ef209(db.res.getString("EF209"));
				result[i].setB_ef210(db.res.getString("EF210"));
				result[i].setB_ef211(db.res.getString("EF211"));
				result[i].setB_ef212(db.res.getString("EF212"));
				result[i].setB_ef213(db.res.getString("EF213"));
				result[i].setB_ef214(db.res.getString("EF214"));
				result[i].setB_ef215(db.res.getString("EF215"));
				result[i].setB_ef216(db.res.getString("EF216"));
				result[i].setB_ef217(db.res.getString("EF217"));
				result[i].setB_ef218(db.res.getString("EF218"));
				result[i].setB_ef219(db.res.getString("EF219"));
				result[i].setB_ef220(db.res.getString("EF220"));
				result[i].setB_ef221(db.res.getString("EF221"));
				result[i].setB_ef222(db.res.getString("EF222"));
				result[i].setB_ef223(db.res.getString("EF223"));
				result[i].setB_ef300(db.res.getString("EF300"));
				result[i].setB_ef301(db.res.getString("EF301"));
				result[i].setB_ef302(db.res.getString("EF302"));
				result[i].setB_ef303(db.res.getString("EF303"));
				result[i].setB_ef304(db.res.getString("EF304"));
				result[i].setB_ef305(db.res.getString("EF305"));
				result[i].setB_ef306(db.res.getString("EF306"));
				result[i].setB_ef307u1(db.res.getString("EF307U1"));
				result[i].setB_ef307u2(db.res.getString("EF307U2"));
				result[i].setB_ef307u3(db.res.getString("EF307U3"));
				result[i].setB_ef308(db.res.getString("EF308"));
				result[i].setB_ef309(db.res.getString("EF309"));
				result[i].setB_ef310(db.res.getString("EF310"));
				result[i].setB_ef311(db.res.getString("EF311"));
				result[i].setB_ef312(db.res.getString("EF312"));
				result[i].setB_ef313(db.res.getString("EF313"));
				result[i].setB_ef314(db.res.getString("EF314"));
				result[i].setB_ef315(db.res.getString("EF315"));
				result[i].setB_ef316(db.res.getString("EF316"));
				result[i].setB_ef317(db.res.getString("EF317"));
				result[i].setB_ef318(db.res.getString("EF118"));
				result[i].setB_ef319(db.res.getString("EF319"));
				result[i].setB_ef320(db.res.getString("EF320"));
				result[i].setB_ef321(db.res.getString("EF321"));
				result[i].setB_ef322(db.res.getString("EF322"));
				result[i].setB_ef323(db.res.getString("EF323"));
				result[i].setB_ef400(db.res.getString("EF400"));
				result[i].setB_ef401(db.res.getString("EF401"));
				result[i].setB_ef402(db.res.getString("EF402"));
				result[i].setB_ef403(db.res.getString("EF403"));
				result[i].setB_ef404(db.res.getString("EF404"));
				result[i].setB_ef405(db.res.getString("EF405"));
				result[i].setB_ef406(db.res.getString("EF406"));
				result[i].setB_ef407u1(db.res.getString("EF407U1"));
				result[i].setB_ef407u2(db.res.getString("EF107U2"));
				result[i].setB_ef407u3(db.res.getString("EF107U3"));
				result[i].setB_ef408(db.res.getString("EF408"));
				result[i].setB_ef409(db.res.getString("EF409"));
				result[i].setB_ef410(db.res.getString("EF410"));
				result[i].setB_ef411(db.res.getString("EF411"));
				result[i].setB_ef412(db.res.getString("EF412"));
				result[i].setB_ef413(db.res.getString("EF413"));
				result[i].setB_ef414(db.res.getString("EF414"));
				result[i].setB_ef415(db.res.getString("EF415"));
				result[i].setB_ef416(db.res.getString("EF416"));
				result[i].setB_ef417(db.res.getString("EF417"));
				result[i].setB_ef418(db.res.getString("EF418"));
				result[i].setB_ef419(db.res.getString("EF419"));
				result[i].setB_ef420(db.res.getString("EF420"));
				result[i].setB_ef421(db.res.getString("EF421"));
				result[i].setB_ef422(db.res.getString("EF422"));
				result[i].setB_ef423(db.res.getString("EF423"));
				db.res.next();
				i++;
			}
			s_logger.log(Level.INFO, "select all ok." + i);
			} 
			else  // keine Zeile gefunden
			{result = null;}; 
		} catch (SQLException ex) {
			s_logger.log(Level.INFO, "SQLException" + ex);
			result = null;
		    throw new EJBException(ex); 
		} catch (NullPointerException e) {
			s_logger.log(Level.INFO, "NullPointerException");
			result = null; // kein resultset
		}finally{
			db.close();
		}
	
	 	return result;
	 	
	 }

Ich habe mir in einer gespeicherten Prozedure anhand der gesetzen paramter eine tabelle gefüllt die genau den Aufbau der Datei haben soll. diese sogenannte temp tabelle würd mit den gewünschten feldern aus andern tabellen gefüllt.
aber ich glaub das sollte ncith groß das problem sein ich habe mein statement ausgeführt mit angabe der parameter. Und bekomme auch mengen von 13.000 sätzen in 7,2 sek .
mein statment kann gewiss noch optimiert werden . aber ich bekomm erst mal das gewünscht resultset.

was sol ich eurer meinung nach tun?
 
Zuletzt bearbeitet:
also ich hab mal grade meine server seite getestet scheint echt an der server seite zu liegen :mad: Mein JUnit test zu dieser holen methode schmeist mir auch ein Outofbounderror : java heap space

wie kann ich jetzt am sinnvollsten mein result füllen damit ich kein fehler bekomm? ab einer kleinen menge von datensätzen ging das ja nooch gut aber anscheinend gibt es aber bei mehr datensätzen echt ein memory leak wenn ich das auf diese weiße mache !


kan mir jemand helfen wäre toll
 
Auf den ersten Blick würde ich sagen, kannst du es vergessen deine Ergebnisse in EINEM Array vom Server auf den Client zu holen.
Das heißt du musst die Serverseite ändern und dir immer handliche Stücke holen. Also dir vom Result die ersten z.B.100 Zeilen geben lassen, die zu deinem Clienten übertragen und behandeln, und dann die nächsten 100 usw.

Leider habe ich nicht so viel Ahnung davon wie man Clien-Server programmiert, wie davon wie man die VM in die Knie zwingt, daher muss dir mit der gestaffelten Datenübertragung jemand anderes helfen.

Das EINE Array mit ALLEN Ergebnissen wird in deinem Falle einfach nicht machbar sein... die Daten sind wohl nicht umsonst in ner Datenbank gespeichert ;)
 
und wie stelle ich das am besten an? ist das überhaupt der richtige Ansatze? Die Leute die schon Serveranwendungen programmiert haben sind nun gefragt!!

freue mich auf vorschläge tips oder weitere ideen..
 
Zurück