Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
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.
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?
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
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.
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:
Code:
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 ?
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
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...
Code:
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
}
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.
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:
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...
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.
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
Code:
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?
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.
@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
Code:
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;");
}
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))
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...
Code:
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:
das dürfte der alles entscheidende codeschnipsel sein aus dem konstruktor von ID3v2Frame
Code:
// 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?
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:
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):
Code:
// 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.