Java Heap Space Exception

Status
Nicht offen für weitere Antworten.

PollerJava

Top Contributor
Hallo,

in meinem Programm hole ich mir Daten aus einer Datenbank und stelle diese mit einem jFreeChart dar, ich hole mir die Daten z.B.: alle 5 sec aus der DB,
nach einer gewissen Zeit (1 Stunde) bekomme ich folgende Fehlermeldung(unten),

Weiß vielleicht jemand, wie ich diese Fehlermeldung beheben kann??

lg und herzlichen Dank für die Antworten,



Code:
Exception in thread "Timer-29" java.lang.OutOfMemoryError: Java heap space
        at java.lang.Class.getDeclaredConstructors0(Native Method)
        at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
        at java.lang.Class.getConstructor0(Class.java:2699)
        at java.lang.Class.getConstructor(Class.java:1657)
        at org.firebirdsql.jdbc.FBStatementFactory.createStatement(FBStatementFactory.java:189)
        at org.firebirdsql.jdbc.AbstractConnection.createStatement(AbstractConnection.java:765)
        at org.firebirdsql.jdbc.AbstractConnection.createStatement(AbstractConnection.java:254)
        at net.ppos.datenbank.DBWriter.fillTable(DBWriter.java:113)
        at net.ppos.datenbank.DBWriter.run(DBWriter.java:93)
        at java.util.TimerThread.mainLoop(Timer.java:512)
        at java.util.TimerThread.run(Timer.java:462)
Exception in thread "Timer-24" java.lang.OutOfMemoryError: Java heap space
        at java.util.LinkedHashMap.createEntry(LinkedHashMap.java:424)
        at java.util.LinkedHashMap.addEntry(LinkedHashMap.java:406)
        at java.util.HashMap.put(HashMap.java:385)
        at sun.util.resources.OpenListResourceBundle.loadLookup(OpenListResourceBundle.java:118)
        at sun.util.resources.OpenListResourceBundle.loadLookupTablesIfNecessary(OpenListResourceBundle.java:97)
        at sun.util.resources.OpenListResourceBundle.handleGetObject(OpenListResourceBundle.java:58)
        at sun.util.resources.TimeZoneNamesBundle.handleGetObject(TimeZoneNamesBundle.java:59)
        at java.util.ResourceBundle.getObject(ResourceBundle.java:380)
        at java.util.ResourceBundle.getObject(ResourceBundle.java:383)
        at java.util.ResourceBundle.getStringArray(ResourceBundle.java:363)
        at sun.util.TimeZoneNameUtility.retrieveDisplayNames(TimeZoneNameUtility.java:100)
        at sun.util.TimeZoneNameUtility.retrieveDisplayNames(TimeZoneNameUtility.java:81)
        at java.util.TimeZone.getDisplayNames(TimeZone.java:399)
        at java.util.TimeZone.getDisplayName(TimeZone.java:350)
        at java.util.Date.toString(Date.java:1024)
        at java.lang.String.valueOf(String.java:2827)
        at org.jfree.data.time.RegularTimePeriod.toString(RegularTimePeriod.java:346)
        at org.jfree.data.time.TimeSeries.add(TimeSeries.java:523)
        at org.jfree.data.time.TimeSeries.add(TimeSeries.java:598)
        at org.jfree.data.time.TimeSeries.add(TimeSeries.java:583)
        at net.ppos.trend.MultipleAxisTrend.createPlot(MultipleAxisTrend.java:219)
        at netk.ppos.trend.MultipleAxisTrend.updatePanel(MultipleAxisTrend.java:185)
        at net.ppos.datenbank.DBDriver.findFile(DBDriver.java:150)
        at net.ppos.component.CheckList.setShift(CheckList.java:115)
        at net.ppos.component.Trend.aktTrend(Trend.java:519)
        at net.ppos.component.TrendAkt.run(TrendAkt.java:36)
        at java.util.TimerThread.mainLoop(Timer.java:512)
        at java.util.TimerThread.run(Timer.java:462)
Exception in thread "EventThread" java.lang.OutOfMemoryError: Java heap space
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
 
Dein Speicher ist voll. Schaufel speicher frei oder wenn das nicht geht, der VM mehr Speicher zuweisen. Vermutlich baust du aber nur systematisch deinen Speicher zu bzw. hast irgendwo ne unglückliche endlos-schleife 😉 .
 
Ja, ich hatte das auch bei den *.svg- Dateien -> Wenn ich 5 geöffnet hatte, dann war der Heap voll nur wo ich jetzt in meinem Code den Speicher kontinuierlich anfülle, ist mir nicht klar?????

Kann ich den Heap explizit leeren, was kommt eigentlich in den Heap- Speicher?
 
als Ergaenzung meines Vorgaengers

java -Xms <size>
Set initial Java heap size. Default: Xms32m

java -Xmx<size>
set maximum Java heap size. default:Xmx128m

z.B.

java -Xms=32m -Xmx=256m <Klassenname>
 
Der GarbageCollecter leert den Heap von selbst. Du kannst in bitten zu gucken, was er leeren kann. Aber ob er das dann macht oder nicht, bleibt ihm überlassen. Generell werden aber auch nur Objekte gelöscht, die nicht mehr benötigt werden, also keine Referenz mehr darauf besteht.

In den Heap kommt alles, was Arbeitsspeicher benötigt (also so ziemlich deine komplette App mit allen Daten 😉 ).
 
ja das kanns ja nicht sein, Mein Programm soll Monate bis Jahr laufen und der Java Heap ist schon nach einer Stunde voll, da hilft mir das vergrößern des Heaps nicht sehr viel,

lg
 
du darfst eben Bilder, die nicht angezeigt werden, nicht im Speicher halten,
vielleicht hast du eine Liste mit vorherigen Bilder oder ähnliches,

sowas ist schwer von außen zu sagen
 
nö nö, die svg- Bilder hab ich eh nicht mehr, ich wollte nur sagen, dass ich, wie ich das mit den *.svg- bildern ausprobiert habe, auch schon mal einen OutOfMemoryError vom Java heap space hatte.

Kann es eigentlich sein, dass das was mit einer ArrayList zu tun hat, welche ich als static definiert habe und wo immer mehr Einträge hinzugefügt werden???

lg
 
Hab jetzt in meinem Code nicht konkretes gefunden, keine Ahnung, was das sein kann,

Kann ich beim Debuggen irgendwie sehen, wie sich der Java Heap füllt?
 
Wenn du ständig Dinge in deine ArrayList hinzufügst, aber nie etwas raus löschst, ist der Heap natürlich irgendwann voll!
 
Du sagst, Du liest alle 5 Sekunden aus der DB. Was soll mit den alten Daten passieren, die Du beim letzten Schritt gelesen hast? Sollen die erhalten bleiben oder brauchst Du die dann nicht mehr?

Ich vermute mal, die brauchst Du dann nicht mehr. Werden Sie denn auch "gelöscht"? Der Teil des Codes ist wahrscheinlich interessant.
 
Also ich mach das so:


Code:
 private HashMap<String, Float> dBWerte = new HashMap<String, Float>();

....


1. rs = con.createStatement().executeQuery("SELECT zeitstempel, wert FROM " + dBName + " WHERE zeitstempel BETWEEN '" + zeitVon + "'" + " AND '" + zeitBis + "'");   // aus DB herausholen

2. xYTrend.updatePanel(dBWerte, name, xSeite, einheit, lineColor, zeitRaum);  // auf jFreePanel darstellen
            

3. dBWerte.clear();    // HashMap clearen


Ich kann da jetzt nichts sehen, was im Speicher bleiben würde, bin aber sehr Dankbar für Verbesserungstipps,

lg
 
Hm. Da stimm ich Dir zu.

Und wo ist Deine statische ArrayList? Was wird mit der gemacht?
 
NTB hat gesagt.:
Hm. Da stimm ich Dir zu.

Und wo ist Deine statische ArrayList? Was wird mit der gemacht?


dbWerte oben war statisch, sonst war alles gleich,

Was bei mir noch statisch ist:


Code:
public static Connection con, con1;  // 2 Verbindungen zur DB
 
Das da ist vermutlich das Problem.
Code:
rs = con.createStatement()...
Meine Vermutung ist, dass du die Connection dauernd offen hälst und die Statements nie freigibst.
Irgendwann mal ist der Speicher voll.

Ich dachte das Thema "Schliessen von ResultSets und Statements" haben wir schon geklärt. (http://www.java-forum.org/de/viewtopic.php?p=323907)
 
Ja ich habs momentan so implementiert, dass ich 2 statische Connection habe,

Mir ist nicht ganz klar, wie der speicher voll werden kann, nur weil ich die Connection statisch habe,
Das sind ja nur 2 Connections die offen sind, oder??

lg
 
Hätte noch eine Frage zu

Code:
stmt = getConnection().prepareStatement(String.format("SELECT zeitstempel, wert FROM %s WHERE zeitstempel BETWEEN ? AND ?", dBName));

Muss ich schreiben

Code:
DriverManager.getConnection(). ...

oder was muss ich da noch schreiben?? Ich bekommen nämlich eine Fehlermeldung - die Methode getConnention() kennt der Kompiler nicht,

lg und vielen Dank
 
?
du hast doch (anscheinend) bisher schon mit Connections und Statements gearbeitet,
also wirst du doch irgendwo schon eine Connection her haben,

getConnection() geht nur wenn die Klasse, in der du dich befindest, eine entsprechende Operation anbietet,
Grundlagenkapitel 1 😉
 
Das getConnection() soll eine Methode von dir sein, wo du eine neue Connection aufbaust oder eine bestehende
zurückgibst. Von mir aus deine statische Connection. Mach aber immer wieder die ResultSets zu, damit der Speicher
freigegeben wird. Und wenn du kein PreparedStatement verwendest, dann das normale Statement ebenfalls freigeben.
Verwendest du wieder PreparedStatement, kannst du es wiederverwenden und beim Beenden des Programms bzw.
beim Schliessen der Connection freigeben.
 
genau so hab ichs jetzt gemacht,
Vielen Dank für die Hilfe,


PS: eine kleine Frage hätte ich noch:
Was hat es damit auf sich, dass ich in meinem SQL Text ein ? hineinmachen und es dann mit dem Statement setzen kann,
ist das allgemein gültig bei Strings oder geht das nur bei Statements

(hab ich noch nie gesehen)

Code:
stmt = con.prepareStatement(String.format("SELECT zeitstempel, wert FROM %s WHERE zeitstempel BETWEEN ? AND ?", dBName));
                        stmt.setTimestamp(1, tsAktStart);
                        stmt.setTimestamp(2, tsAktEnd);
 
Das sind Platzhalter in PreparedStatement. Die Werte werden dann, JDBC-Treiber abhängig, im korrekten Format
gesetzt.

z.B.
Code:
PreparedStatement stmt = getConnection().prepareStatement(
   "SELECT DISTINCT schnitzel, pommes, mayo"
  +"  FROM tblKantine"
  +" WHERE (preis_schnitzel + preis_pommes + preis_mayo) < gehalt/100)"
  +"   AND schnitzel_haltbarkeitsdatum > ?"
  +"   AND schnitzel_maul_und_klauenseuche = false"
  +"   AND pommes_frittierfett = ?"
  +"   AND mayo_konsistenz NOT LIKE ?"
  +"   AND koch_alkoholintus <= 0.8"
  +"   AND kassentussi LIKE '90,60,90'"
);

stmt.setDate(1, new Date()); // Parameterindex beginnt immer mit 1
stmt.setDate(2, new Date());
stmt.setString("%salmonellenbiotop%");
...
😀
 
Korrektur
Code:
stmt.setString(3, "%salmonellenbiotop%");
 
Vielen Dank,


Jetzt habe ich noch ein Problem und zwar beim schreiben in die DB,

Ich habe folgende Methode (unten), wenn ich diese Ausführe, bekomme ich aber folgende Fehlermeldung:

Code:
Fehler Klasse beim Schreiben in die Tabelle  : org.firebirdsql.jdbc.FBSQLException: No resultset for sql
Fehler Klasse beim Schreiben in die Tabelle  : org.firebirdsql.jdbc.FBSQLException: No resultset for sql


Was mache ich da falsch??

herzlichen Dank!!





Code:
 protected synchronized void fillTable(String tableName, Timestamp kommen, float wert, Timestamp gehen, Timestamp quit, String alarmNr, int var1, int var2)
            {
            try {
                PreparedStatement stmt = null;   
               
                    stmt = DBDriver.con.prepareStatement(String.format("INSERT INTO %s (zeitstempel, wert) VALUES ( ? , ?)", tableName));
                    stmt.setTimestamp(1, kommen);
                    stmt.setFloat(2, wert);
                    stmt.executeUpdate();
                    
                }
            catch (SQLException e) 
                {
                System.out.println("Fehler Klasse DBWriter beim Schreiben in die Tabelle " + tableName + " : " + e);
                }
            }
[/code]
 
Wollte "stmt.executeUpdate();" schreiben


Ich benutze jetzt eine Connection zum herauslesen und zum hineinschrieben in die DB, bekomme jetzt aber wieder die Exception:

Code:
Fehler in der Klasse DBDriver beim Auslesen aus der DB: org.firebirdsql.jdbc.FBSQLException: The resultSet is closed
Fehler in der Klasse DBDriver beim Auslesen aus der DB: org.firebirdsql.jdbc.FBSQLException: The resultSet is closed
Fehler in der Klasse DBDriver beim Auslesen aus der DB: org.firebirdsql.jdbc.FBSQLException: Result set is already closed.
Fehler in der Klasse DBDriver beim Auslesen aus der DB: org.firebirdsql.jdbc.FBSQLException: The resultSet is closed
Fehler in der Klasse DBDriver beim Auslesen aus der DB: org.firebirdsql.jdbc.FBSQLException: The resultSet is closed

Wie gibts das?
Muss ich auch 2 Connections verwenden??
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben