ERLEDIGT
NEIN
NEIN
ANTWORTEN
12
12
ZUGRIFFE
699
699
EMPFEHLEN
-
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 :1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
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.
Geändert von IzYaBoi (22.09.08 um 10:43 Uhr)
-
22.09.08 11:46 #2
- Registriert seit
- Jun 2002
- Ort
- Saarbrücken (Saarland)
- Beiträge
- 9.886
- Blog-Einträge
- 29
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ß TomJava rocks!
How to become a good Java Programmer?
Does IT in Java and .Net
The only valid measurement of code quality: WTFs / minute
Blog
Xing
Twitter
-
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.There are 10 kind of people, those who understand binary and those who don't.
-
ich hab jetzt mal alles nochmal auskommentiert.
Code java:1 2 3 4 5 6 7 8 9 10 11 12 13 14
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
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 OoGeändert von Oliver Gierke (22.09.08 um 13:36 Uhr) Grund: Code tags spendiert
-
22.09.08 13:35 #6
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!In theory, there is no difference between theory and practice. In practice, there is!
www.olivergierke.de
-
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 :1 2 3 4 5 6 7 8 9 10
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 :1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
/** * 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?Geändert von IzYaBoi (22.09.08 um 14:03 Uhr)
-
also ich hab mal grade meine server seite getestet scheint echt an der server seite zu liegen
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
There are 10 kind of people, those who understand binary and those who don't.
-
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..
-
23.09.08 12:32 #11
Hi,
bei Client-/Serveranwendungen (wie überall) ist die Performance sehr wichtig. Daher würde ich meinen Vorrednern beipflichten - unterteile Deine Ergebnisse in Häppchen.
Bei Strings z.B. kann man im Extremfall byte weise übertragen.
Noch ein anderes Problem: Selbst ein gutes DBMS ist nicht schnell, wenn man ein select macht, bei welchem n-tausend Zeilen herauskommen. Deshalb hier ein Denkansatz mit etwas Pseudocode.
Du solltest die Ergebnisspalten von vornherein mit einem "limit" SQL Befehl begrenzen. Oder/und: Du könntest die Abfrage nach IDs in Intervalle unterteilen (where id between startIndex and endIndex).
Dann iterierst Du die Indexe hoch, z.B.:
- startIndex=0, endIndex =100
- Abfrage
- wenn Ergebnis wirklich 99 Zeilen umfasst, zähle hoch
- startIndex = 101, endIndex = 200
- Abfrage
- usw...
Zusätzlich kannst Du probieren,
Jedes Ergebnis ResultSet zeilenweise zu senden/empfangen.
Das Senden initiierst Du, indem Du einen Buffer (z.B. ResulSet Array) einrichtest,
der beim Senden abgearbeitet wird. D.h. für jede erfolgreiche Abfrage fügst Du einem (z.B.) ArrayList Buffer dieses ResultSet hinzu. Dann iterierst Du die BufferList durch,
gibst die Ergebnisse in dem jeweiligen ResultSet aus
Noch ein Tipp: Check mal Dein Programm auf Rekursionen.
Selbst bei noch so vielen Array Einträgen, ist ein OOME unwahrscheinlich.
In Deinem Code gibt es Möglichkeiten für Rekursionen in Methoden, allerdings kann ich die ja nicht einsehen/nachprüfen.
Ruft Dein Programm sich irgendwo irgendwie selbst auf?
VG Tim
-
Der out of Memory ist hier gar nicht so unwahrscheinlich, auch ohne Rekursion.
Ein Result Objekt hat immerhin 100 Strings (geschätzt) bei 10 k Ergebnissen kommt man auf 1Mio Strings. lass die jeweils im Schnitt 128Byte groß sein, und schon Kommst du auf einen Speicherbedarf von 128MByte was dem schon beträchtlich nah kommen sollte, was der Server einem einzelnen Prozess zugestehen dürfte.
Die vorgeschlagene Lösung fürs portionieren scheint mir der beste weg. da so keine Änderungen an der Serverseite nötig werden.There are 10 kind of people, those who understand binary and those who don't.
-
rekursion schließe ich aus aber bin mittlerweile an einer andern Lösung ich sag euch dann wenn ich fertig bin was ich gemacht habe
Ähnliche Themen
-
java.lang.OutOfMemoryError in Schleifenkonstrukt
Von Johannes7146 im Forum JavaAntworten: 16Letzter Beitrag: 30.07.09, 12:20 -
java.lang.OutOfMemoryError: Java heap space
Von MopsdeBops im Forum JavaAntworten: 2Letzter Beitrag: 09.12.08, 09:33 -
[ERROR]: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
Von fenerli23 im Forum JavaAntworten: 10Letzter Beitrag: 21.01.08, 15:42 -
JTable gibt java.lang.OutOfMemoryError
Von silbsch im Forum JavaAntworten: 3Letzter Beitrag: 08.03.07, 09:29 -
java.lang.OutOfMemoryError
Von Sirakov im Forum JavaAntworten: 12Letzter Beitrag: 15.02.05, 21:36





Zitieren

Login





