# Java Heap Size -Xmx1024m reicht nicht!



## vimar (9. Mrz 2012)

hallo, muss ein riesen objekt speichern (standartserialisierung), ich kriege 

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.ibjectOutputStream$HandleTable.growEntries(ObjectOutputStream.java:2327)

diesen fehler:








hab mit superfetch ausgemacht, per rammap den standby gelöscht, hab 2,3 GB frei, müsste doch meiner meinung nach dann -Xmx2048m machen , geht aber nicht, vm meldet immer dass es nicht klar geht soviel zu reservieren (obwohl 2,3 gb frei). schaffe nur bis 1400m. und das reicht auch nicht.


einzige möglichkeit: neues mainboard, 64bit win7 und 6 GB ram?!?

oder kann man irgendwie noch an den parametern richtig rumspielen bzw hab schon überlegt obs nicht ne möglichkeit gibt den heap irgendwie auf disk umzusteuern auch wenns mega langsam wäre denke ich?

bitte um ideen, will ungerne nen neuen rechner kaufen weil student -.-

anmerkung:

OS: win7 32bit professional
ram: 3 GB ddr2
cpu: 2,2ghz dualcore intel


----------



## Spacerat (9. Mrz 2012)

Ich weis zwar nicht, was genau du da serialisierst aber vllt. produzierst du dabei zu viel Datenmüll in zu kurzer Zeit. D.h, dass beim Serialisieren evtl. immer neue Puffer angelegt werden, statt alte wiederzuverwenden und dass mehrfach in Zeiträumen, in denen der GC kaum die Referenzen der alten Puffer weggeräumen und damit den durch diese verwendeten Speicher wieder freigeben kann. Gegen solche Probleme gibt es 2 Möglichkeiten.
1. Verwendung von DirectBuffer (java.nio) oder
2. Object-Reuse.


----------



## vimar (9. Mrz 2012)

verschachtelte arraylisten. und zwar ziemlich viele.

hiermit schreibe ich auf disk:


```
public static void writeKMEANS_ClusterList_to_DB_noXML(){
        
        try{
            
            FileOutputStream datei = new FileOutputStream("kmeansClusterlist.ser");
          //  ByteArrayOutputStream baos = new ByteArrayOutputStream(datei);
            ObjectOutputStream o = new ObjectOutputStream(datei);
           System.out.println("Clusterlist wird nun gespeichert!");
            o.writeObject(KMEANS.ClusterList);
            System.out.println("Clusterlist gespeichert!");
            o.close();
            
        }
        catch(IOException e){
            System.err.println(e);
        }
        
    }
```

ich google jetzt mal nach deinen vorschlägen. meinst du es ist darauf anwendbar?


----------



## irgendjemand (9. Mrz 2012)

@TO
wow ... was zur hölle hast du mit deinem win7 angestellt das du nur so wenig speicher verbrauchst ?
wenn ich mal in meinen res monitor gucke *Win7 Ulti x64 und ne ganze menge im hintergrund* sieht das eher so aus

770MB HARDWARE
1140MB USED
60MB CACHE
1835MB STAND BY
300MB FREE

diese werte sind eine moment aufnahme fast dierekt nach dem booten ..
im laufe der runtime ändert sich das ganze natürlich ... vor allem beim zocken ... aber grob hab ich immer etwas mehr als 1GB in use *da ich ja wie gesagt ULTI hab und ne ganze menge im hintergrund lafen lasse*

[OT]im system sind 4GB RAM verbaut ... mein bios tut sich damit allerdings schwer und meldet WIN nur 3,2GB verwendbaren RAM ...
allerdings kommt der "fehlende" RAM meiner graka zu gute *hat nativ 512MB ... im tool steht 1,3GB* ... da mein bios wohl das was er WIN nicht zuteilen kann dierekt umleitet ...
ich weis nicht was besser ist : performance-boost da graka anstatt nativen 512MB nun fette 1,3GB hat ... oder das mir in WIN rund 800MB fehlen ... fürs gamen ist auf jeden fall der graka boost besser*[/OT]

mich hindert es nicht daran mal eben einem java-programm 2GB zuzuweisen *habe es sogar mal mit platten-caching auf ganze 2,5GB gebracht ... allerdings war mein WIN extrem langsam und musste alle hintergrund-programme und -dienste abschalten ... aber es ging xD*

zu deinem screenshot
WIN meldet zwar angeblich satte 2,3GB FREE *wow ... das wäre ein traum das mal bei mir zu sehen* ... aber sieh dir doch mal RAM MAP an ... dort steht eindeutig : 1,27GB UNUSED ... und genau das ist der wirklich freie RAM

ich kenne RAM MAP zwar nicht *obwohl ich andere SysInternals-programme durch aus intensiv nutze* ... aber ich kann mir vorstellen das dort der RAM nicht wirklich aufgeräumt ... sondern für windows nur so um-gepackt wird das windows diesen ganzen shadow-RAM als FREE sieht ... was aber nicht der fall ist *vermutlich wird auch ne ganze menge auf platte gecached um das zu erreichen -> performance verlust*

zum x86 allgemein : bei 32bit plattformen hast du das problem das diese max 2GB RAM dierekt addressieren können ... und du damit EINER anwendung auch nur max 2GB zuteilen kannst ...
das andere problem : der RAM wird nicht "aufgeräumt" sein ... sondern nur "zerlöchert" ... das heißt : die 1,27GB angeblich FREE RAM stehen vermutlich NICHT *in einem zusammhängenden block ohne löcher* zur verfügung ... und genau da knallt es bei den meisten programmen ... und bei der java-vm ganz besonderst ...

was also erstmal passieren müsste wäre ein richtiges aufräumen und defragmentieren des RAM ... genau so wie das defrag einer platte alle daten schön in einem block hintereinander anordert und den freien platz als einen zusammhängenden großen block ans "ende" verschiebt ... müsste das mit dem RAM ebenfalls geschehen ...

das ist so aber leider nicht möglich ... denn RAM hat im gegensatz zu anderen datenträgern keine feste struktur-zuordnung ...
alleine wenn dual- oder triple-channel verwendet wird werden logisch aufeinanderfolgende speicherzellen über mehrere bänke geteilt ... wodurch der sinnvolle zusammenhang zwischen logischer und physischer ordnung des RAM verloren geht ...
wenn z.b. der RAM *logisch* schön defragmentiert ist ... könnte es physisch auf den bänken nach einem wilden chaos aussehen ... anderst rum verhält es sich genau so : wenn der RAM *physisch* aufgeräumt ist sieht es logisch nach einem ziemlich zerstückelten wirr-warr aus in dem man nirgends größere zusammenhängende blöcke mehr findet ...


worauf ich letztendlich hinaus will : man darf es mit den ganzen anzeigen über "freien RAM" , "rest-zeiten" und der gleichen nicht so genau nehmen ... schon gar nicht bei windows *wer erinnert sich nicht an das Win98 Setup welches im vorletzten schritt ungefähr 10min-15min auf "Restzeit : 7min" hing ...* ... wobei ich auch annehme das andere systeme nicht 100% genau sind *und es auch gar nicht können* ...
darum solltest du nicht versuchen die plattform auf das programm anzupassen ... *also so wie du es versuchst : du hast ein programm was ewig viel RAM braucht den du nicht zur verfügung hast* ... sondern das programm an die plattform *wenn man es sauber implementiert und auch platten-caching sinnvoll verwendet brauchen selbst größere programme nicht mehr als die standard 64MB der VM* ...

nach diesem kleinen exkurs solltest du dir also überlegen : macht es überhaupt sinn eine solch komplexe struktur aufzubauen *verschachtelte array-listen ... das klingt nach enorm viel overhead* ... und *viel wichtiger* : *müssen unbedingt ALLE informationen gleichzeitig im RAM liegen ?*

wir hatten erst neulich ein ähnliches thema bei dem jemand mit risiegen arrays irgendetwas berechnen wollte ...
wenn man das ganze nicht so stark parallelisiert das man auch wirklich mehrere hunderte berechnung wirklich synchron ausführen kann ... sonndern nur ein paar wenige ... und diese auch nur "pseudo-parallel" ... macht es dann überhaupt sinn trotzdem alle daten im RAM zu halten ? NEIN ...

und genau das solltest du dich fragen : ist es wirklich unbedingt notwendig das alle daten auf ein mal im RAM liegen ... und müssen diese auch wirklich als ein risieges objekt mit sehr viel overhead gespeichert werden ... ODER : ist es möglich die verschachtelungen zu lösen und wirklich nur die teile im RAM zu haben mit denen man auch gerade wirklich arbeitet ?
eine einfache umsetzung wäre das du nicht auf der obersten ebene serialisierst ... also alles in ein risieges objekt packst ... sondern auf der untersten ... also z.b. ein kleineres array von vielleicht 50 einträgen zu je einem block serialisierst und dann nur bei verwendung von platt lädst *was natürlich vorraussetzt das die objekte innerhalb des arrays nicht noch weiter verschachteln in dem diese z.b. auch noch weitere arrays enthalten*

du würdest natürlich einen großen geschwindigkeits-einbruch haben da immer wieder daten auf die platte geschrieben und auch wieder von dieser gelesen werden müssen ... *wofür man ja eigentlich den RAM hat um eben genau dort die daten für schnellen zugriff zu halten* ... aber ein programm schreiben was selbst bei knapp 1,5GB immer noch mit einem fehler ala "kein RAM" aussteigt ... obwohl man selbst scheinbar nicht mal die möglichkeit hat diese auch bereit zu stellen *3GB und dann quälst du da ein Win7 Pro drauf ? wie gesagt : ich bin übberascht das bei dir weniger als und 850MB verwendet werden *persönlicher "tiefst-" rekord auf nem Win7 pro x86 bei nem freund**

du solltest also noch mal grundlegend darüber nachdenken ob es wirklich notwendig ist so viel RAM überhaupt zu verwenden ...
du würdest z.b. schon einen großteil des overhead einsparen in dem du die array*listen* nicht verschachtelst ... sondern am stück in ein array schreibst ... weil java kennt keine multi-dimensionalen arrays ... sondern nur "arrays von arrays" ... was deutlich mehr overhead zur folge hat ...
dann wie gesagt : nur die daten im RAM halten mit denen du in diesem momment auch wirklich arbeitest ... alles andere was gerade eh nur sinnlos platz verschwendet raus auf die platte schreiben und erst bei bedarf laden


aber mach dir mal keine sorge ...
du bist nicht der einzige der sowas kompliziertes gebastelt und dann festgestellt hat das es so nicht geht
sowas ist auch schon hochbezahlten profis passiert ... die einfach n schlechten tag hatten ...

du siehst : ein neues system mit mehr resourcen ist gar nicht notwendig ... du musst dein programm nur so umschreiben das es die begrenzten resourcen die du hast auch sinnvoll nutzt ... und RAM vollballern gehört nun mal nicht dazu ... manchmal muss man wirklich zwischen performance und resourcen-anforderung wählen ...


----------



## Empire Phoenix (9. Mrz 2012)

Transparenten cache einbauen wäre ne Lösung

ersetze alle array zugriffe druch get und set methoden die in eienr eigenen klasse sind,
diese läd dann jeweils den benötigten wert von der platte (sofern nicht im speicher) und behält die letzten 1gb werte im speicher, der rest wird automatisch bevor neue geladen werden erstmal ausgeschrieben. (bei seriellen zugriff kann man das lesen natürlich blockweise machen, immer 64 mb auf einmal oder so)

Ansonsten die standart serialisierung ist nicht sehr effizient, wenn es sich um arras mit x*y handelt und die objecte darinnen primitve sind zb alles floats könnte man dafür einfach einen data output stream nehmen, der die der reihe nach runterschreibt.
(standart serialisierung muss wegen referenzen ect das gesammte object im ram behalten bis es fertig ausgeschreiben wurde, die alternative im extremfall nur 1 double plus das outputstreamobject


----------



## bone2 (9. Mrz 2012)

irgendjemand hat gesagt.:


> @TO
> wow ... was zur hölle hast du mit deinem win7 angestellt das du nur so wenig speicher verbrauchst ?
> wenn ich mal in meinen res monitor gucke *Win7 Ulti x64 und ne ganze menge im hintergrund* sieht das eher so aus
> 
> ...


[OT]du hast 2,1 gb frei, also fast genauso viel. win7 nimmt sich mehr ram, je mehr man hat. bei 8 gb sieht man dann wo die grenze liegt (bei 3 gb). win7 beschleunigt damit prozesse, buffert häufig verwendetes vor usw. außerdem vermeidet man damit die nutzung der super lahmen auslagerungsdatei.

das du nur 3.2 gb angezeigt bekommst, liegt an 32 bit. (2^32 (= 4 mrd) adresssen für alles im system und wie du richtig festgestellt hast, gehört dazu auch alles aufm mainboard und erweiterungskarten.

also 64 bit windows, 64 bit java, 8 gb ram und ab gehts.

ein einzelnes programm kann unter 32 bit windows nur 2gb adressieren.[/OT]


----------



## vimar (9. Mrz 2012)

ums auf den punkt zu bringen:

ich denke ich muss(sollte) alles im ram haben.

in meiner "bachelorarbeit" gehts um "content based image retrieval" mit "query by image". 

so. ich nutze "SIFT feautures" & "k-means algorithmus" derzeit. 

pro bild hab ich ca. 2000 vektoren mit 128 dimensionen. bei meiner kleinen trainingsbasis (150 bilder) hab ich derzeit 310.000 vektoren (grob gerechnet mit 300.000 vektoren * 128 ~ 30 Millionen Zahlen) und die gilt es zu speichern als "ein" objekt.


da ich im "kmeans"-algorithmus permanent und wiederholend mittelwerte berechnen muss, wäre es irgendwie fatal wenn nicht alles im ram drin is -.-


----------



## bone2 (9. Mrz 2012)

dir die von der uni geschenkte 64 bit version von w7 runterladen und ram kaufen is keine option? wieso besorgen sich leute immernoch 32 bit betriebssysteme...


----------



## vimar (9. Mrz 2012)

ahhh, hab mir meinen code einfach eben nochmal länger angesehn  und "unwichtige" arraylisten mit transient von der serialisierung ausgeschlossen -.- muss derzeit jetzt nur 16KB (ja kilobyte) anstatt 2-3 GB speichern und es klappt! sorry für die umstände, hab sinnlosen kram abspeichern wollen!


----------



## XHelp (9. Mrz 2012)

@vimar, du solltest auch vlt mal eine andere Darstellungsart deiner Dokumentenvektoren versuchen. Oft werden Vektoren beim Clustern nicht als Liste gespeichert, sondern als Map. Viele Dimensionen werden vermutlich eh 0 sein, da lohnt es sich nicht diese auch noch mitzuschleppen.


----------



## tuxedo (9. Mrz 2012)

vimar hat gesagt.:


> muss derzeit jetzt nur 16KB (ja kilobyte) anstatt 2-3 GB speichern und es klappt! sorry für die umstände, hab sinnlosen kram abspeichern wollen!



Das muss mördermäßig verdammt viel gewesen sein dass du jetzt nur noch einen verschwindend geringen Bruchteil - um genau zu sein rund "ein hundersechundfünzigtausendzweihundertfünfzigstel" (mit 2,5gb gerechnet) - an Daten speichern musst. Das muss ja wie ein Schlag vor den Kopf gewesen sein als du deinen Fehler entdeckt hast?!


----------



## vimar (9. Mrz 2012)

ja die ganzen verschaltelten arraylisten die letztendlich nur im ram sein müssen UM durch den algorithmus zu den ergebnissen zu kommen die ich aber nicht abspeichern muss sondern nur die ergebnisse -.- und die belaufen sich auf deutlich weniger speicher ;P


----------



## irgendjemand (10. Mrz 2012)

vimar hat gesagt.:


> ja die ganzen verschaltelten arraylisten die letztendlich nur im ram sein müssen UM durch den algorithmus zu den ergebnissen zu kommen die ich aber nicht abspeichern muss sondern nur die ergebnisse -.- und die belaufen sich auf deutlich weniger speicher ;P



da haben wir es doch : zu viel daten im RAM

da du selbst sagst das du einen großteil an daten nur für berechnung brauchst könntest du deinen algorythmus auch noch soweit optimieren das halt wie gesagt auch nur die menge an daten im RAM liegen mit denen du gerade rechnest ... denn ich denke nicht das du mit allen daten gleichzeitig rechnest *selbst wenn du threads verwendest wird das alles nur eher pseudo-parallel ... je nach dem wie viele cores/threads die CPU hat*

das das ganze aber am ende auf 16KB zusammenschrumpft ... ok ... deutet auf schlechte daten-organisation und ne menge overhead hin ... vielleicht mal debuggen ob irgendwelche daten "0" bzw "null" sind und dann versuchen diese wegzuoptimieren ...



bone2 hat gesagt.:


> dir die von der uni geschenkte 64 bit version von w7 runterladen und ram kaufen is keine option?


DAS ist definitiv KEINE option ... und selbst wenn ihm seine uni eine x64 zur verfügung stellt ... ist immer noch die frage ob die hardware das auch komplett mitmacht



bone2 hat gesagt.:


> wieso besorgen sich leute immernoch 32 bit betriebssysteme...


darauf würde ich geteilter meinung antworten

1) es gibt heute immer noch systeme welche kein x64 können *z.b. die meisten NETbooks auf Intel Atom basis oder andere* bzw ältere systeme welche immer noch ihren dienst tun *vermutlich nicht gerade die leistung für Win7 haben und daher eh vermutlich XP drauf läuft ... aber wäre ein grund*

2) ich kenne den aktuellen preislichen unterschied zwischen verschiedenen windows versionen nicht ... aber ich weis das ich damals für mein win7 ulti x64 ne ganze menge gezahlt habe *ich brauche den ganzen kram aber auch ... eine professional wäre nicht ausreichend gewesen* ... und das die x86 version welche daneben im regal stand um einiges billiger war ...
kurz um : finanzielle gründe ...

3) OEM : wenn sich ein systemhersteller dazu entscheided ein system nur mit x86 OS und software an einen kunden auszuliefern ist schon ein ziemliches problem ... denn in der regel bezahlt man bei "fertig-systemen" das OEM OS mit ... warum sollte man also noch mal extra geld für ein retail-OS ausgeben ?

du siehst also : es gibt verschiedene gründe warum es heutzutage immer noch leute gibt die ein x86 OS fahren ... *obowohl mir das alles selbst zu wider ist da ich weder OEM produkte kaufe noch es mir am finanziellen fehlt*


----------



## vimar (10. Mrz 2012)

hab jetzt für 40 euro nen neues mainboard gekauft für meinen e2200, und 4 gb ram gekauft. hab nun 7 GB ram und ubuntu 11.10 64bit installiert. gleich mal netbeans installieren und -Xmx hochschrauben xD xD xD


----------



## irgendjemand (10. Mrz 2012)

hmm .. ich enthalte mich mal einem "geistlichen erguss" über diese "radikale totschlag-lösung" ...


----------

