# mysql to many connections



## rambozola (8. Sep 2005)

huhu,

in meinem java prog greife ich auf eine mysql-db zu...nachdem ich nun einen JavaOutOfMemoryError beseitigts habe stürzt das programm ab mit der meldung zu viele connections für meine mysql-db.

also habe ich im mysql-handbuch gelesen,wie man die anzahl der connections erhöhen kann.

wenn ich richtig liege geht das zB mit 

GRANT root with MAX_CONNECTIONS_PER_HOUR = 1000;

leider funktioniert das nicht u er meldet einen fehler in der mysql-syntax.

ich benutze mysql 4.0.25.

hat einer von euch ne idee?  :bahnhof:


----------



## Bleiglanz (8. Sep 2005)

mach gelegentlich einen close()

1000 Connections sind und "Last" Gesichtspunkten einfach zuviel, wozu brauchst du das??


----------



## rambozola (8. Sep 2005)

habs selber rausbekommen...man sollte die sql-connection schon schließen und nicht nur neue dazu öffnen sonst ist bei 100 schluß.

sorry ich bin unwürdig  :lol:


----------



## thE_29 (8. Sep 2005)

Man sollte auch die ResultSets und die Statements closen so nebenbei ^^


----------



## rambozola (8. Sep 2005)

hmm zu früh gefreut ich hab da noch probleme mit der reihenfolge...wenn ich das resultset close befor ichs zuückgebe dann gehts logischerweise nicht.

ich hab ne klasse MySQLVerwaltung seh ich das richtig das ich da die Connection,ResultSet und Statement als Klassenvariablen anlegen muss und dann alle 3 dinge direkt nach dem zugriff auf das resultset und verwendung im programm aus ner anderen klasse closen muss?


----------



## rambozola (8. Sep 2005)

lol jetzt close ich die verbindungen ordentlich direkt nach jedem zugriff auf meine db und nun hab ich wieder nen OutOfMemoryError (heap) obwohl ich mein programm schon mit den parametern "-Xms512m -Xmx1024M" starte.

mehr geht nicht da mehr als 1024 MB hauptspeicher hab ich nicht.

hat jemand noch ne idee ausser hauptspeicher kaufen?  :lol: 

der fehler tritt übrigens nur beim einlesen von manchen cds auf nicht bei allen.

achso...mein programm liest cds ein und schreibt das ganze in ne mysql-db 

ich wär über jeden tip sehr dankbar.


----------



## Mag1c (8. Sep 2005)

Hi,

warum verwendest du die Connection nicht wieder ? Beim Start eine erzeugen, diese immer wieder benutzen und beim Beenden des Programms die Connection schließen ?

und zum OOM:
schließt du die ResultSets nun ? Poste doch mal ein Stück Code.

Gruß
Mag1c


----------



## rambozola (8. Sep 2005)

die resultsets sollten schließen

ich rufe nämlich nach jedem zugriff aus der steuerklasse die methode allesClosen() (siehe unten im code) auf

hier der code meiner klasse mysqlverwaltung


```
/*
 * Created on 14.07.2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
 
package MySQLVerwaltung;

import java.sql.*;

/**
 * @author winnie
 * 
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

public class MySQLVerwaltung {
	
	 public String anfrageString = "";
	 //public Connection conMySQL = null;
	 //für Verbindung
	 String url,user,password;
	 Connection conMySQL = null;
	 Statement myStatement = null;
	 PreparedStatement pStatement = null;
	 ResultSet myResult = null;

	 public MySQLVerwaltung(String url,String user,String password,String query){
		this.url = url;
		this.user = user;
		this.password = password;
	 	this.anfrageString = query;
	 	try {conMySQL = DriverManager.getConnection(
		          "jdbc:mysql://"+url,user,password);    
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			//System.out.println("fehler im konstruktor mysqlverwaltung "+e.toString());
			//e.printStackTrace();
		}
		  }
		
	/**
	 * methode überprüft,ob nach einfügen u löschen in den unterschiedlichen tabellen keine widersprüchlichen daten gespeichert sind(zb FS)
	 *
	 */
	public void integritaetDerDBChecken(){
		
	}
	public ResultSet getResultSet() {
	    try {
	      Class.forName("com.mysql.jdbc.Driver").newInstance();
	    }
	    catch (ClassNotFoundException e) {
	      System.out.println("Treiber nicht gefunden");
	    }
	    catch (InstantiationException e) {
	      System.out.println("InstantiationException");
	    }
	    catch (IllegalAccessException e) {
	      System.out.println("IllegalAccessException");
	    }

	    
	    
	    
	    
	    try {
	    	    	
	      myStatement = conMySQL.createStatement();
	      myResult = myStatement.executeQuery(anfrageString);
	      }
	    catch (SQLException ex) {
	      System.out.println("Fehler in getResultSet(): "+ex.toString());
	    }
	    
	    return myResult;
	    
	  }
	/**
	 * Methode sendet die der MySQLVerwaltung im Konstruktor übergebene Anfrage an die DB
	 * und löst eine SQLException aus im Fehlerfall
	 */
	
	
	  public void sqlAnfrageAnDBSchicken() throws SQLException {
	  try {
	    Class.forName("com.mysql.jdbc.Driver").newInstance();
	  }
	  catch (ClassNotFoundException e) {
	    System.out.println("Treiber nicht gefunden");
	  }
	  catch (InstantiationException e) {
	    System.out.println("InstantiationException");
	  }
	  catch (IllegalAccessException e) {
	    System.out.println("IllegalAccessException");
	  }

	  //ResultSet myResult = null;
	  	if(conMySQL != null){
		    pStatement = conMySQL.prepareStatement(anfrageString);
		    //PreparedStatement myStatement = conMySQL.prepareStatement(anfrageString);
		    
		    pStatement.executeUpdate();
		    //usr_web3_1 ist der name der datenbank
		    //myResult = myStatement.executeQuery(anfrageString);
	  	}
	}
	
	public void allesClosen(){
		try {
			if(conMySQL != null){
				conMySQL.close();
			 }
			
			if(myStatement != null){
			 	myStatement.close();
			 }
			if(pStatement != null){
				pStatement.close();
			 }
			if(myResult != null){
				myResult.close();
			 }
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			System.out.println("fehler bei allesClosen() "+e.toString());
			e.printStackTrace();
		}
		 	 
	}

}
```

was ich aber merkwürdig finde ist das die java.exe im taskmanager nie über 60 MB kommt was ja eh schon  unter standartmaximum der jvm ist.

und ich hab sogar mit dem parameter -Xmx1024M bis zu 1 GB hauptspeicher bereitgestellt.

wie kann das sein?


----------



## Mag1c (8. Sep 2005)

Hi,

also das "Treiber laden" machste mal nur im Konstruktor vor dem holen der Connection oder besser noch in einem static {} Block außerhalb jeglicher Methoden.

Die Connection kannste schon im Konstruktor öffnen. Das läßt sich aber auch in eine Methode getConnection() auslagern:


```
public Connection getConnection () {
    if ( conMySQL == null ) {
        conMySQL = ...
    }
    return conMySQL;
}
```

Da du nicht für jede Anfrage eine neue Instanz von MySQLVerwaltung erstellen willst, nimmst du die query aus dem Konstruktor raus und übergibst die query stattdessen den beiden Abfragemethoden. (Die man durchaus auch in queryMySQL(String query) und updateMySQL(String query) umbenennen könnte).

Die ResultSets kannst du sicher auch außerhalb schließen. Ich bin mir nicht sicher, ob du die Statements nach dem DB-Zugriff schließen darfst und anschließend trotzdem noch auf die ResultSets zugreifen kannst. Das mußt du ausprobieren.

Die Connection schließt du erst, wenn das Programm beendet wird.

Das mit dem Speicher kommt mir auch komisch vor. Bist du sicher, daß das mit dem -Xmx tatsächlich auch bei der VM angekommen ist ?

Gruß
Mag1c


----------



## rambozola (8. Sep 2005)

hab mir mal die werte im javaprogramm ausgeben lassen bevor er die exception wirft

speicher bei mp3file 0 von 119:
maxMemory= 66650112
freeMemory= 497240
totalMemory= 2756608
**************************************************************************
speicher bei mp3file 1 von 119:
maxMemory= 66650112
freeMemory= 329416
totalMemory= 2756608
**************************************************************************
speicher bei mp3file 2 von 119:
maxMemory= 66650112
freeMemory= 587360
totalMemory= 2756608
**************************************************************************
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

das kann doch eig nurn bug in der jvm 1.5.0.1 sein oder?

ich weiss echt nicht mehr weiter....hat noch jemand ne idee?


----------



## Mag1c (8. Sep 2005)

also maxMemory entsprechen in etwa 64MB
freeMemory sind ca. 300-500 kB

da kommt das mit dem OOM schon hin.

die großen Fragen sind nun:

1. warum zieht das -Xmx nicht ?
2. wieso wird überhaupt so viel Speicher verbraucht ?

zu 1.: gib mal Infos, wie du dein Prog startest.
zu 2.: schau mal mein Posting oben und guck ob sich dann was ändert.

Gruß
Mag1c


----------



## rambozola (8. Sep 2005)

max memory geht nicht weil ich die ausgabe ausm eclipse habe u dort die -Xmx parameter nicht funktionieren(hab ich im netz gelesen)..ich starte mein programm aber sonst aus der konsole...ich schau mir jetzt mal dort an ob der max_speicher dort höher ist u der parameter funktioniert


----------



## rambozola (8. Sep 2005)

in der konsole zieht der parameter -Xmx und obwohl noch über 100 MB speicher frei sind stürzt er ab

maxMemory= 1065484288
freeMemory= 108249688
totalMemory= 1028390912

komisch....


----------



## Mag1c (8. Sep 2005)

bau mal den DB-Teil um. Wenns nix bringt, mußte noch mehr Code posten 

Gruß
Mag1c


----------



## Mag1c (8. Sep 2005)

Doppelpost  irgendwas stimmt mit dem Forum grade nicht.

Gruß
Mag1c


----------



## rambozola (8. Sep 2005)

habe mein programm jetzt mühsam umgebaut u arbeite nur noch mit einer db-connection im ganzen programm...leider gibts den speicherfehler immer noch


----------



## rambozola (8. Sep 2005)

habe jetzt auch mal ein System.gc() eingebaut (--> Garbage Collection) 
bringt auch nichts

**************************************************************************
speicher bei mp3file 50 von 72:
maxMemory= 66650112
freeMemory= 1919600
totalMemory= 3989504
**************************************************************************
speicher bei mp3file 51 von 72:
maxMemory= 66650112
freeMemory= 1907280
totalMemory= 3989504
**************************************************************************
speicher bei mp3file 52 von 72:
maxMemory= 66650112
freeMemory= 1894936
totalMemory= 3989504
**************************************************************************
speicher bei mp3file 53 von 72:
maxMemory= 66650112
freeMemory= 1882624
totalMemory= 3989504
**************************************************************************
speicher bei mp3file 54 von 72:
maxMemory= 66650112
freeMemory= 1875832
totalMemory= 3989504
**************************************************************************
speicher bei mp3file 55 von 72:
maxMemory= 66650112
freeMemory= 2010992
totalMemory= 4136960
**************************************************************************
speicher bei mp3file 56 von 72:
maxMemory= 66650112
freeMemory= 1998664
totalMemory= 4136960
**************************************************************************
speicher bei mp3file 57 von 72:
maxMemory= 66650112
freeMemory= 1985600
totalMemory= 4136960
**************************************************************************
speicher bei mp3file 58 von 72:
maxMemory= 66650112
freeMemory= 1978728
totalMemory= 4136960
**************************************************************************
speicher bei mp3file 59 von 72:
maxMemory= 66650112
freeMemory= 1965720
totalMemory= 4136960
**************************************************************************
speicher bei mp3file 60 von 72:
maxMemory= 66650112
freeMemory= 1952752
totalMemory= 4136960
**************************************************************************
speicher bei mp3file 61 von 72:
maxMemory= 66650112
freeMemory= 1939712
totalMemory= 4136960
**************************************************************************
speicher bei mp3file 62 von 72:
maxMemory= 66650112
freeMemory= 1933616
totalMemory= 4136960
**************************************************************************
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

obwohl der free memory halbwegs konstant bleibt stürzt java ab...echt misteriös

der wert des free memory war beim starten des programmes geringer als beim absturz...


----------



## rambozola (8. Sep 2005)

das ist der ausschnitt meiner "monstermethode" (weil so lang) das sicher für den OutOfMemoryError verantworlich ist.

ist es vielleicht der vector der an allem schuld ist?

der fehler tritt auch nur bei manchen cds/dvds auf....es ist komisch weil ne dvd mit 700 mp3´s sollte mehr speicher verbrauchen als ne cd mit 100 mp3s...


```
for (int i = 0; i < v.size(); i++) {
					
					//dateiendung ermitteln
					StringTokenizer st = new StringTokenizer(((File)v.elementAt(i)).getName(),".");
					do{dateiEndung = st.nextElement().toString().toLowerCase();
						
					}while(st.hasMoreElements());
					
					String dateTime = aenderungsDatumBestimmen(((File)v.elementAt(i)));
					String verzeichnisAufMedium = verzeichnisAufMediumBestimmen(((File)v.elementAt(i)));
					
					// ein "\" im verzeichnisname führt zu syntaxfehler im mysql
					//deswegen noch ein "\"hinzufügen
					
					verzeichnisAufMedium = verzeichnisAufMediumMitUmgedrehtenBackSlash(verzeichnisAufMedium);
					verzeichnisAufMedium = this.kommasInDateiNameEntfernen(verzeichnisAufMedium);
					verzeichnisAufMedium = this.hochKommasInDateiNameEntfernen(verzeichnisAufMedium);
					/********************************************************/
					if(verzeichnisAufMedium.length() > 140){
						//inDateiFuerDebuggingSchreiben("verzeichnisAufMedium zu lang");
					verzeichnisAufMedium = verzeichnisAufMedium.substring(0,140);
					}
										
					/********************************************************/
					
					//int dateiGroesse = ((int)((File)v.elementAt(i)).length())/(1024*1024);
					double dateiGroesseDouble = Math.rint( ((double)((File)v.elementAt(i)).length()/(1024*1024)) * 100 ) / 100.;    
					float dateiGroesseFloat = (float)dateiGroesseDouble;
					//System.out.println("gefundene dateiGroesse für datei "+((File)v.elementAt(i)).getName()
							//+" = " +dateiGroesseFloat);
					//bei dateiname kommas entfernen da sonst mysql-syntax nicht stimmt
					String nameOhneKommata = "";
					if(((File)v.elementAt(i)).getName().indexOf(",")!= -1){
						//System.out.println("gefundener name mit komma = "+((File)v.elementAt(i)).getName());
					nameOhneKommata = kommasInDateiNameEntfernen(((File)v.elementAt(i)).getName());
					}
										
					if(((File)v.elementAt(i)).getName().indexOf("'")!= -1){
						//System.out.println("gefundener name mit hochkomma = "+((File)v.elementAt(i)).getName());
					nameOhneKommata = hochKommasInDateiNameEntfernen(((File)v.elementAt(i)).getName());
					}
					else{
						nameOhneKommata = ((File)v.elementAt(i)).getName();
					}
					/********************************************************/
					if(nameOhneKommata.length() > 100){
						//inDateiFuerDebuggingSchreiben("nameOhneKommata zu lang");
					nameOhneKommata = nameOhneKommata.substring(0,100);
					}
					/********************************************************/
					String anfrageString = "insert into DATEI values(null,'"+dateiEndung+"'," +
									dateiGroesseFloat+",'"+nameOhneKommata+"'," +
									dateTime+",'"+verzeichnisAufMedium+"',"+medienErkennung.tempDatenTraeger.nrDesMediums+");";
					
					//inDateiFuerDebuggingSchreiben(mp3MySQL.anfrageString);
					//dateien einzeln eintragen 
					try {
					 	 dbconnection.sqlAnfrageAnDBSchicken(anfrageString);
					 	dbconnection.pStatement.close();
					 	 
					} catch (SQLException e) {
						//inDateiFuerDebuggingSchreiben("SqlException beim datei schreiben (1414): "+e.toString());
						//System.out.println(e.toString());
						e.printStackTrace();
					}
					
					//einträge in tabelle mp3File
					int dateinr = -1; //ist der fremdschlüssel in der tabelle mp3file von tabelle datei
					
					
					
					
						//fs dateinr holen
						anfrageString = "select dateinr from DATEI where dateiEndung = '"+
						dateiEndung+"' and dateiName = '"+ nameOhneKommata +
						"' and datumLetzteDateiAenderung = "+dateTime+" and verzeichnisAufMedium = '"+
						verzeichnisAufMedium+"' and nrDesMediums = "+ +medienErkennung.tempDatenTraeger.nrDesMediums+";";
										
						//inDateiFuerDebuggingSchreiben("anfragestring = "+mp3MySQL.anfrageString);
						
						//System.out.println("anfragestring = "+mp3MySQL.anfrageString);
						try {
						ResultSet res = dbconnection.getResultSet(anfrageString);
						
						while(res.next()){
						dateinr = res.getInt(1);
						//inDateiFuerDebuggingSchreiben("gefundene dateinr = "+dateinr);
						
						}
						dbconnection.myResult.close();
						dbconnection.myStatement.close();
						
						
					} catch (SQLException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
						//inDateiFuerDebuggingSchreiben("SqlException beim dateinr holen (1437): "+e1.toString());
					}
					if(dateinr != -1){
						String verzeichnisAufMediumUnbehandelt = verzeichnisAufMediumBestimmen(((File)v.elementAt(i)));
						String nameDerMP3Datei = ((File)v.elementAt(i)).getName();
						MP3File tempMP3File = null;
						try {
							tempMP3File = new MP3File(verzeichnisAufMediumUnbehandelt,nameDerMP3Datei);
							} catch (ID3v2WrongCRCException e2) {
								// TODO Auto-generated catch block
								//e2.printStackTrace();
								//System.out.println("ID3v2WrongCRCException gecatcht ");
							} catch (ID3v2DecompressionException e2) {
								// TODO Auto-generated catch block
								//e2.printStackTrace();
								//System.out.println("ID3v2DecompressionException gecatcht ");
							} catch (ID3v2IllegalVersionException e2) {
								// TODO Auto-generated catch block
								//e2.printStackTrace();
								//System.out.println("ID3v2IllegalVersionException gecatcht ");
							} catch (IOException e2) {
								// TODO Auto-generated catch block
								//e2.printStackTrace();
								//System.out.println("IOException gecatcht ");
							} catch (NoMP3FrameException e2) {
								// TODO Auto-generated catch block
								//e2.printStackTrace();
								//System.out.println("NoMP3FrameException gecatcht ");
							}
							
							String songTitel = null,interpret= null,tracklaenge= null,
							genre= null,jahr= null,album= null;
							int bitrate = -1;
							
							
							try {
								
								//titel bestimmen
								TagContent tempTagContent = tempMP3File.getTitle();
								 songTitel = tempTagContent.getTextContent();
								
								if(songTitel != null){
									if(songTitel.indexOf("'")!= -1){
										songTitel = this.hochKommasInDateiNameEntfernen(songTitel);
										}
									if(songTitel.indexOf(",")!= -1){
											songTitel = this.kommasInDateiNameEntfernen(songTitel);
										}
								}
								if(songTitel != null && songTitel.equals("")){
									songTitel = null;
									
								}
								
								//System.out.println("songtitel = "+songTitel);
								//interpret bestimmen
								tempTagContent = tempMP3File.getArtist();
								interpret = tempTagContent.getTextContent();
								if(interpret != null){
									if(interpret.indexOf("'")!= -1){
										interpret = this.hochKommasInDateiNameEntfernen(interpret);
										}
									if(interpret.indexOf(",")!= -1){
										interpret = this.kommasInDateiNameEntfernen(interpret);
										}
								}
								if(interpret != null && interpret.equals("")){
									interpret = null;
									
								}
								
								
								//System.out.println("interpret = "+interpret);
								
								//trackläenge
								tempTagContent = tempMP3File.getTime();
								tracklaenge = tempTagContent.getTextContent();
								if(tracklaenge == null){
									long trackDauerInSekunden = tempMP3File.getLength();
									int stunden = (int)trackDauerInSekunden/(60*60);
									int minuten = ((int)trackDauerInSekunden - (stunden * 3600))/60;
									int sekunden = (int)trackDauerInSekunden - (stunden * 3600) - (minuten * 60);
									tracklaenge = stunden+":"+minuten+":"+sekunden;
									//System.out.println("trackdauer = "+stunden+":"+minuten+":"+sekunden);
									
								}
								//System.out.println("tracklaenge = "+tracklaenge);
								
								//genre
								tempTagContent = tempMP3File.getGenre();
								genre = tempTagContent.getTextContent();
								if(genre != null){
									if(genre.indexOf("'")!= -1){
										genre = this.hochKommasInDateiNameEntfernen(genre);
										}
									if(genre.indexOf(",")!= -1){
										genre = this.kommasInDateiNameEntfernen(genre);
										}
								}
								if(genre != null && genre.equals("")){
									genre = null;
									
								}
								if(genre != null){
									int start = genre.indexOf("(");
									int stop = genre.indexOf(")");
									//wenn (genreNr) in genreTag
									if(stop != -1 && start != -1){
										//System.out.println("nr im tag; genre vor zuordnung= "+genre);
										int genreNr = Integer.parseInt(genre.substring(start+1,stop));
										genre =genreMp3NachNrZuordnen(genreNr); //genreName zuordnen
										//tempTagContent = tempMP3File.getTitle();
										//System.out.println("nr im tag; genre nach zuordnung= "+genre
											//	+"; genrenr = "+genreNr+" für den titel "+tempTagContent.getTextContent());
										
									}
									
								}
								//System.out.println("genre = "+genre);
								
								//bitrate
								 bitrate = tempMP3File.getBitrate();
								//System.out.println("bitrate = "+bitrate);
								
								 //jahr
								tempTagContent = tempMP3File.getYear();
								 jahr = tempTagContent.getTextContent();
								if(jahr != null){
									if(jahr.indexOf("'")!= -1){
										jahr = this.hochKommasInDateiNameEntfernen(jahr);
										}
										if(jahr.indexOf(",")!= -1){
											jahr = this.kommasInDateiNameEntfernen(jahr);
										}
								}
								if(jahr != null && jahr.equals("")){
									jahr = ""+0000;
									
								}
								try{
									Integer.parseInt(jahr);
								}
								catch(NumberFormatException nfe){
									jahr = ""+0000;
								}
								
								
								//System.out.println("jahr = "+jahr);
								
								//album
								tempTagContent = tempMP3File.getAlbum();
								album = tempTagContent.getTextContent();
								if(album != null){
									if(album.indexOf("'")!= -1){
									album = this.hochKommasInDateiNameEntfernen(album);
									}
									if(album.indexOf(",")!= -1){
									album = this.kommasInDateiNameEntfernen(album);
									}
								}
								if(album != null && album.equals("")){
									album = null;
									
								}
							} catch (FrameDamagedException e3) {
								// TODO Auto-generated catch block
								//e3.printStackTrace();
								//System.out.println("FrameDamagedException endlich gecatcht");
							}
							
								//System.out.println("album = "+album);
								
//								mp3dateien anlegen
								anfrageString = "insert into mp3file values(null,'"+songTitel+"','"+
								interpret+"','"+tracklaenge+"','"+genre+"',"+bitrate+","+jahr+",'"+album+"',"+dateinr+");";
								//System.out.println("mp3MySQL.anfrageString = "+mp3MySQL.anfrageString);
								try {
									dbconnection.sqlAnfrageAnDBSchicken(anfrageString);
									dbconnection.pStatement.close();
									
								} catch (SQLException e4) {
									// TODO Auto-generated catch block
									//e4.printStackTrace();
									System.out.println("sqlfehler bei mp3MySQL.anfrageString: "+e4.toString());
								}
								
					System.gc();			
					speicherDatenAusgeben(i,v.size());			
							
						
						
					}
					else{
						System.out.println("dateinr = "+dateinr+" konnte nicht ermittelt werden");
					}
					
					//closen damit heap entlasten und max_connections überschritten vermieden wird
					
					
				}
```


----------



## Mag1c (9. Sep 2005)

Hi,

also das sieht alles recht linear aus. Glaub nicht, daß der Haken in dieser Methode steckt.
Du müsstest mal alle sub-Methoden checken (posten?) die du dort benutzt. Ich vermute mal,
daß dort bei bestimmten Daten/Files irgendwas schief läuft. Benutzt du irgendwo Rekursion ?

Wenn du nicht debuggen magst, bau einfach mal um jeden Methoden-Aufruf ein System.out.println
drumrum. Das gibt zwar ne Menge Ausgaben aber du weißt dann sofort, wo er als letztes war, bevor
die OOM-Exception kam.

Gruß
Mag1c


----------



## rambozola (9. Sep 2005)

hi,

ich les meine dateien rekursiv in nen vector ein...aber wenn er abstürzt ist er in der monstermethode die ich dir oben gepostet habe.dort muss also der bug sein...

ich poste dir aber gerne meine methode zum rekursiven einlesen:


```
private void rekursivDateienEinlesen(File einzulesenderOrdner, Vector files) {
		File[] fileArray = einzulesenderOrdner.listFiles();
		for(int i = 0; i < fileArray.length;i++){
			if(fileArray[i].isFile()){
			files.add(fileArray[i]);
			}
			if(fileArray[i].isDirectory()){
				rekursivDateienEinlesen(fileArray[i],files);
			}
		}
		
	}

}
```

ich glaube eher das beim berechnen der bitrate oder ähnlichem der mp3datei etwas schiefläuft...der fehler tritt bei manchen medien (cds/DVDs) schon bei der 9. datei und bei anderen erst nach 300 auf...es kann eig nur etwas mit den id3-tags zu tun haben...aber alle 25 klassen der mp3-jar-datei kann ich hier nicht posten ;-)

weiterhin hatte ich den outofmemoryerror ja auch schon obwohl ich beim absturz mehr free memory als zu programmstart hatte

hab nen profiler gestern mal installiert und drüberlaufen lassen..ausser das ich fast 30 % meiner programmzeit in der geposteten monstermethode verbringe bin ich da nicht schlauer geworden.

mein thread müsste eig verschoben werden und nen anderen titel wie "outofmemoryerror (heap) trotz free memory" bekommen...wie geht das?

danke übrigens @Mag1c für dein konstantes bemühen..ansonsten scheint ja keiner ne meinung hier zu meinem problem zu haben...


----------



## Mag1c (9. Sep 2005)

Hi,

ja, es muß irgendwo innerhalb der "Monstermethode" (*schönes Wort*) passieren. Das mit der Rekursion war nur so eine Idee, weil man bei sowas sehr schnell mal ein OOM bekommt.

1. laß dir doch mal die Dateinamen ausgeben. Dann kopierst du die Datei, wo der OOM kommt, irgendwo einzeln in ein Verzeichnis und läßt dein Programm mal da drüberlaufen. Wenn dann der Fehler wieder auftritt, hat die Datei irgendwas, was dein Programm aus dem Tritt bringt. Kommt der Fehler nicht, liegts nicht an der Datei selbst sondern irgendwie an der Verarbeitungssequenz.

2. mach mal das mit den System.out.println (wie oben schon angesprochen). Da die "Monstermethode" ziemlich monströs ist, ist das eher ein Stochern im Nebel, wenn du nicht mal genauer einkreisen kannst, wo der Fehler genau auftritt.

3. Einen Profiler brauchste erst, wenn alles zu langsam ist  Mit dem Debugger könntest du z.B. einen Breakpoint am Anfang der "Monstermethode" setzen, dich mit F8 (Eclipse->Run->Resume) bis zu der betreffenden Datei durchhangeln und dann Schritt für Schritt live verfolgen, was da passiert. Damit solltest du recht schnell herausfinden, was schief geht.

Gruß
Mag1c


----------



## rambozola (9. Sep 2005)

das mit den printlns is ne gute idee gewesen...hab mich damit durch die klassen gehangelt und den fehler eingegrenzt.

ich hab jetzt die zeile gefunden wo der outofmemoryerror bei manchen dateien passiert


```
public ID3v2(File file) throws IOException,
            ID3v2IllegalVersionException, ID3v2WrongCRCException,
            ID3v2DecompressionException {
	/* hier kommt die fehlerhafte zeile */	
        this(new FileInputStream(file));
      /* das war die fehlerhafte zeile */
System.out.println("file = "+file.getName());
		System.out.println("nach this(new FileInputStream(file))");
        this.file = file;
		System.out.println("nach this.file = file;");

    }
```

ich hab die zeile markiert wo der fehler passiert und der speicher (angeblich) überläuft...file wird mit this von mp3file übergeben...mp3file ist von file abgeleitet..

das hilft mir jetzt aber trotzdem nicht allzuviel weiter....noch ne idee?


----------



## Mag1c (9. Sep 2005)

Hi,

na das ist doch schon mal ein großer Schritt. In der Klasse muß es noch mind. einen weiteren Konstruktor
geben "ID3v2(FileInputStream ... )" dort geht die Suche weiter.

Gruß
mag1c


----------



## rambozola (9. Sep 2005)

@Mag1c: ja du hast recht ich hab das gar nicht geschnallt mit dem this weil ich so nicht selber programmiere.

ich mach gleich mal weiter und durchforste die anderen konstruktoren die aufgerufen werden...

übrigens hab mir ne cd gebrannt mit nur 2 fehlerhaften liedern...er bricht schon beim ersten lied mit dem OOM ab..soviel ram kann er also noch gar nicht "verbrutzelt" haben in der kurzen zeit....ich melde mich gleich nochmal falls ich mehr entdecke....

übrigens die konstruktoren


```
public ID3v2(InputStream in) throws IOException,
            ID3v2IllegalVersionException, ID3v2WrongCRCException,
            ID3v2DecompressionException {
        this.file = null;

        // open file and read tag (if present)
        try {
            readHeader(in);
        } catch (NoID3v2HeaderException e) {
            // no tag
            header = null;
            extended_header = null;
            frames = null;
            in.close();
            return;
        }

        // tag present
        if (header.hasExtendedHeader()) {
            readExtendedHeader(in);
        } else {
            extended_header = null;
        }

        readFrames(in);

        in.close();
        is_changed = false;
    }

    /**
     * Provides access to <code>file</code>'s ID3v2 tag
     * 
     * @param file
     *            File to access
     * @exception IOException
     *                If I/O errors occur
     * @exception ID3v2IllegalVersionException
     *                If file contains an IDv2 tag of higher version than
     *                <code>VERSION</code>.<code>REVISION</code>
     * @exception ID3v2WrongCRCException
     *                If file contains CRC and this differs from CRC calculated
     *                from the frames
     * @exception ID3v2DecompressionException
     *                If a decompression error occured while decompressing a
     *                compressed frame
     */
    public ID3v2(File file) throws IOException,
            ID3v2IllegalVersionException, ID3v2WrongCRCException,
            ID3v2DecompressionException {
		
        this(new FileInputStream(file));
System.out.println("file = "+file.getName());
		System.out.println("nach this(new FileInputStream(file))");
        this.file = file;
		System.out.println("nach this.file = file;");

    }
```


----------



## Mag1c (9. Sep 2005)

Hi,

ich hab mich mal kurz umgesehen. Du benutzt die MP3-Klassen von hier:

www.vdheide.de/java_mp3/

ja ? Ich hab so den Verdacht, daß da ein Bug drin ist, der eben nur unter
ganz bestimmten Bedingungen auftritt. D.h. dein Code ist soweit in Ordung,
der Fehler liegt in der Bibliothek. (soweit die Theorie)

Versuch doch mal, den Autor zu kontaktieren. Also nicht, daß ich dir nicht
weiter helfen wollte. Aber wenn das so ist, wie ich gerade vermutet hab,
dann wird die Fehlersuche hier über das Board zu aufwendig.

(Falls du den Autor nicht erreichst oder ihn nicht kontaktieren willst, ich könnte
mir das zuhause auch mal fix anschauen. Dazu bräuchte ich allerdings eines der
besagten MP3-Files (oder ich schau mal, ob ich bei mir eins finde))

Gruß
Mag1c


----------



## rambozola (9. Sep 2005)

hi ,

ja genau diese biblio benutz ich und ich musste schon viel umschreiben so dass ne arrayindexoutofboundsexception und ne arithmeticexception abgefangen werden

hab den fehler jetzt komplett eingekreist...


```
while ((bis.available() > 0) && (cont == true)) {
            frame = new ID3v2Frame(bis);
			
            if (frame.getID() == ID3v2Frame.ID_INVALID) {
                // reached end of frames
				
                cont = false;
            } else {
				
                frames.addElement(frame);
				
            }
        }
```

in dieser while-schleife im else zweig läuft sich das programm tot...frames.addelement(frame) wird dabei nur 8x ausgeführt....ja ich kann dirn nen mp3file schicken...von über 130 eingelesenen medien hatten nur 5 den OOM..die suche will ich dir lieber ersparen :wink: 

müsstest mir dann mal deine emailadresse geben.


----------



## rambozola (9. Sep 2005)

das dürfte der alles entscheidende codeschnipsel sein aus dem konstruktor von ID3v2Frame


```
// check if id is valid (no real check for errors, as you will see)
        if (head[0] == 0) {
            // id may not start with a 0
            // you may call it "error", I call it "padding"
            // so do not raise an exception, just inform user of this
            // instance by setting id = ID_INVALID
            this.id = ID_INVALID;
            return;
        }
```

wenn die id nicht mit 0 startet wird die id nie auf ID_INVALID gesetzt und die while-schleife läuft länger als normal (quasi ewig)....die frage ist was ich da tun kann?


----------



## Mag1c (9. Sep 2005)

Hi,

also MP3 ist angekommen (per Mail). Der Fehler OOM ist bei mir genauso aufgetreten. Habe mal ein wenig
debuggt und weiß auch, warum der Fehler kommt. Ich versuche das mal zu erklären.

Ein ID3-Tag besteht ja aus mehreren verschidenen Werten. Dabei ist nun nicht fest vorgeschrieben, wo welche
Information steht, sondern es kommt immer zuerst eine ID, um welchen Wert es sich handelt und dann noch
wieviele Daten er beinhaltet. Anhand der ID kann man die Zuordnung machen (Titel, Artist, Album ...)
In der Lib sind das dieser ID3v2Frames.

Das MP3, was du gechickt hast, enthält einen defekten ID3v2-Header und die Bibliothek fängt das nicht sauber
(bzw. garnicht) ab. Wenn du mit einem Hex-Editor reinschaust, gleich am Anfang:


```
0000:0000 49 44 33 03 00 00 00 00 02 14 54 43 4f 4e 00 00 ID3.......TCON..
0000:0010 00 08 00 00 00 54 6f 70 68 69 74 73 43 4f 4d 4d .....TophitsCOMM
0000:0020 00 00 00 11 00 00 00 65 6e 67 00 53 6f 75 6e 64 .......eng.Sound
0000:0030 6d 61 63 68 69 6e 65 54 41 4c 42 00 00 00 07 00 machineTALB.....
0000:0040 00 00 50 6c 61 74 7a 31 54 50 45 31 00 00 00 12 ..Platz1TPE1....
0000:0050 00 00 00 47 6f 6d 62 61 79 20 44 61 6e 63 65 20 ...Gombay Dance 
0000:0060 42 61 6e 64 54 49 54 32 00 00 00 0f 00 00 00 53 BandTIT2.......S
0000:0070 75 6e 20 4f 66 20 4a 61 6d 61 69 63 61 54 59 45 un Of JamaicaTYE
0000:0080 52 00 00 00 05 00 00 00 31 39 38 30 54 53 49 5a R.......1980TSIZ
0000:0090 00 00 00 08 00 00 00 34 30 31 36 37 31 35 4d 50 .......4016715MP
0000:00a0 33 65 78 74 20 56 33 2e 33 2e 31 36 28 61 6e 73 3ext V3.3.16(ans
0000:00b0 69 29 20 4d 50 33 65 78 74 20 56 33 2e 33 2e 31 i) MP3ext V3.3.1
```

dort findest du die ID's

TCON   8 Bytes
COMM  17 (0x11) Bytes
TALB   7 Bytes
TPE1    18 (0x12) Bytes
TIT2    15 (0x0F) Bytes
TYER   5 Bytes
TSIZ   8 Bytes

wieder. Abschließend müsste als Endekennung als ID eine 0 kommen. Kommt aber nicht.
Beginnend in der 3. Zeile von unten kommt nun die ID "MP3e" was wohl der Name
von irgend einem Tool aber keine ID3-ID ist. Und als Größe ist dort zufällig irgendwas
um die 2 GB kodiert. Die Lib versucht den Speicher zu allokieren und bum OOM 

Zur Lösung des Problems hast du nun zwei Möglichkeiten:

1. repariere die ID3-Tags in den betreffenden MP3s

2. erweitere die Lib um eine Überprüfung der IDs. Das könnte in der Klasse ID3v2Frame
geschehen (so als Idee, die gültigen IDs müsste man sich organisieren):


```
// decode id
        StringBuffer tmp = new StringBuffer(4);
        for (int i = 0; i < 4; i++) {
            tmp.append((char) (head[i] & 0xff));
        }
        this.id = tmp.toString();
        if ( !isValidId(this.id) )
            return;
```

so, hab bis nächste Woche erstmal keine Zeit reinzuschauen. Aber das sieht ja jetzt
schon viel klarer aus. Hoffe, du kommst damit zurecht.

viele Grüße
Mag1c


----------

