# Java Heap Space Exception



## PollerJava (16. Aug 2007)

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,




```
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
```


----------



## The_S (16. Aug 2007)

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  .


----------



## PollerJava (16. Aug 2007)

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?


----------



## Guest (16. Aug 2007)

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>


----------



## The_S (16. Aug 2007)

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  ).


----------



## PollerJava (16. Aug 2007)

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


----------



## SlaterB (16. Aug 2007)

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


----------



## PollerJava (16. Aug 2007)

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


----------



## The_S (16. Aug 2007)

Natürlich. Schonmal versucht 1.000.000 Sätze auf ein DIN A4 Papier zu quetschen  .


----------



## PollerJava (16. Aug 2007)

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?


----------



## The_S (16. Aug 2007)

Wenn du ständig Dinge in deine ArrayList hinzufügst, aber nie etwas raus löschst, ist der Heap natürlich irgendwann voll!


----------



## NTB (16. Aug 2007)

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.


----------



## PollerJava (16. Aug 2007)

Also ich mach das so: 



```
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


----------



## NTB (16. Aug 2007)

Hm. Da stimm ich Dir zu.

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


----------



## PollerJava (16. Aug 2007)

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:



```
public static Connection con, con1;  // 2 Verbindungen zur DB
```


----------



## NTB (16. Aug 2007)

Ok, ich muss passen. Da müssen mal Profis ans Werk


----------



## The_S (16. Aug 2007)

Poste doch mal deinen kompletten Code, der alle 5 Sekunden ausgeführt wird.


----------



## Guest (16. Aug 2007)

Das da ist vermutlich das Problem.
	
	
	
	





```
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)


----------



## PollerJava (16. Aug 2007)

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


----------



## PollerJava (16. Aug 2007)

Hätte noch eine Frage zu 


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

Muss ich schreiben 


```
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


----------



## SlaterB (16. Aug 2007)

?
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


----------



## PollerJava (16. Aug 2007)

Ja bin ich jetzt auch draufgekommen, nachdem mir NetBeans angeboten hat, diese Methode zu erzeugen 

 :idea: 


lg


----------



## Guest (16. Aug 2007)

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.


----------



## PollerJava (16. Aug 2007)

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)


```
stmt = con.prepareStatement(String.format("SELECT zeitstempel, wert FROM %s WHERE zeitstempel BETWEEN ? AND ?", dBName));
                        stmt.setTimestamp(1, tsAktStart);
                        stmt.setTimestamp(2, tsAktEnd);
```


----------



## The_S (16. Aug 2007)

Das ist ein Feature von Statements


----------



## Guest (16. Aug 2007)

Das sind Platzhalter in PreparedStatement. Die Werte werden dann, JDBC-Treiber abhängig, im korrekten Format
gesetzt.

z.B.
	
	
	
	





```
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%");
...
```


----------



## Guest (16. Aug 2007)

Korrektur
	
	
	
	





```
stmt.setString(3, "%salmonellenbiotop%");
```


----------



## PollerJava (16. Aug 2007)

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:


```
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!!






```
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]


----------



## NTB (16. Aug 2007)

Was steht denn in der API ,wie das mit dem Insert geht?


----------



## SlaterB (16. Aug 2007)

edit: siehe NTB


----------



## PollerJava (16. Aug 2007)

Wollte "stmt.executeUpdate();" schreiben


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


```
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??


----------

