# JVM Maximaler HeapSize



## artchi (15. Jul 2016)

Hallo! Ich bin bzgl. des Parameters -Xmx verwirrt. Dieser gibt ja die maximale Heap-Größe an, die Java verwenden soll. Ohne Angabe sind es bei meinem Java 1.8.0_40 (32 Bit Windows Client VM) nur 256 MByte.
Laut JVM 1.6 Docu soll die JVM angeblich autom. 50% vom RAM des PCs reservieren. Tut es aber anscheinend nicht, da mein PC 8 GB RAM hat.

Heißt das, das alle Heap-Objekte wirklich nur 256 MByte verbrauchen können, und dann gibt es ein Out of Memory?

Gibt es eine Möglichkeit der JVM zu sagen, das sie einfach so viel Speicher benutzen können soll, wie möglich ist? Oder muss ich als Entwickler wirklich eine Grenze setzen?


----------



## Cromewell (15. Jul 2016)

Hey, du kannst unter den System-/Benutzervariabeln die Grenze setzen. Doch bei einer 32Bit Arch. ist es, glaube ich, auf 1,4GB beschränkt.


----------



## artchi (15. Jul 2016)

Ich will ja gerade keine Begrenzung. ;-) Er soll sich so viel abzwacken, wie er technisch kann und braucht. Bei einem 32 Bit-System wären es ja ca. 3,5 GByte. Ich verstehe halt nicht, warum ich den Anwender in seiner Arbeit beschränken soll? Weil bei der erzeugung von dynamischen Daten, sagt "dynamisch" ja schon aus, das es keine Vorhersage geben kann.

Aber es sieht so aus, als ob ich z.B. einfach die Grenze auf 3 GByte setzen sollte um Ruhe zu haben?


----------



## Thallius (15. Jul 2016)

Wenn Deine Applikation 3GB RAM braucht würde ich mir erstmal Gedanken über das Gesamtkonzept machen...


----------



## nvidia (15. Jul 2016)

Dem Post fehlen reichlich Informationen. Z.B. welches Betriebssystem wird verwendet, 32 o 64 Bit? Die Tatsache wie denn die maximale Heapgröße ermittelt wurde. Und dann die Annahme das Informationen über das Verhalten von Java 6 auf Java 8 übertragbar wären.

Mit java -XX:+PrintFlagsFinal -version kann man sich übrigens in der Konsole die JVM-Settings anzeigen lassen und je nach System das mit einem grep HeapSize oder findstring verbinden.


----------



## nvidia (15. Jul 2016)

Thallius hat gesagt.:


> Wenn Deine Applikation 3GB RAM braucht würde ich mir erstmal Gedanken über das Gesamtkonzept machen...



Aha, und das Wissen welche Art von Anwendung er hat, hast du woher? Dir ist schon klar das es Java-Programme gibt die im mehrstellingen Gigabytebereich arbeiten und auch noch Off-Heap-Strukturen nutzen, weil es z.B. Simulationsprogramme sind oder große Datenmengen verarbeitet werden müssen usw.


----------



## artchi (15. Jul 2016)

Java 1.8.0_40 32-Bit für Windows 7 64-Bit.
Ermittlung:
_java -XX:+PrintFlagsFinal -version 2>&1 | findstr
MaxHeapSize
  uintx MaxHeapSize  := 268435456_

zusätzlich zur Laufzeit der Anwendung:
_long maxBytes = Runtime.getRuntime().maxMemory();
     System.out.println("Max memory: " + maxBytes / (1024 * 1024) + "M");_
Ausgabe:
_Max memory: 247M_


----------



## nvidia (15. Jul 2016)

Client oder Server JVM?


----------



## artchi (15. Jul 2016)

Es gibt bei uns Anwender die riesige Tabellen rein laden und auch in mehreren Tabs offen haben. Es sind nicht zwangsweise 3 GByte. Aber wenn jemand gerne 10 Tabellen öffnen will, und die dann auch noch als Excel-Datei (mittels POI) exportieren will, dann will ich ihm nicht sagen "die Grenze ist auf 1 GByte gesetzt". Da wird er mich fragen, warum er dann 4+ Gbyte im PC hat? 

Wenn ich in C++ programmiere, startet mein Programm auch nicht mit einer Heap-Grenze. Sondern es zwackt sich das ab, was es braucht. Notfalls greift dann halt das VirtualMemory des OS ein.


----------



## artchi (15. Jul 2016)

nvidia hat gesagt.:


> Client oder Server JVM?


Client-VM. Es ist eine Swing-Anwendung mit OSGI. Das Gesamtpaket (also JAR-Bundles) ist ca. 130 MByte groß.


----------



## nvidia (15. Jul 2016)

Davon abgesehen kannst du dir nicht während der Laufzeit mehr Speicher holen, es sei denn du greifst auf Off-Heap-Geschichten zurück das ist aber eine ganz andere Baustelle.


----------



## nvidia (15. Jul 2016)

Client Heap berechnet sich anders als der Server Heap. Ich bin von einer Server JVM ausgegangen. Für die Client hat sich, glaube ich seit 1.6 wirklich nichts geändert. Habe mir die betroffene Stelle angeschaut, da steht nicht das er 50% des physischen Speichers nimmt, da steht 50% des physischen Speichers bis zu einer größe von 192 Megabytes wenn nicht mehr da ist anderfalls ein Viertel des physischen Speichers bis zu einer Größe von 1GB. Mehr Speicher wird ignoriert, so dass du bei einem Viertel von 1GB landest, was die 256 MB erklärt.

Persönlich würde ich keine Client JVM nehmen die startet zwar minimal schneller, optimiert aber nicht so heavy wie die Servervariante. Des Weiteren würde ich zur 64 Bit greifen, es sei denn irgendwelche nativen Bibliotheken hindern dich daran. Die 64 Bit Variante verwendet intern bis zu einer gewissen Heapgröße komprimierte Pointer d.h. dein Speicherverbrauch verdoppelt sich nicht.


----------



## artchi (15. Jul 2016)

Danke für die Erklärung! OK, das mit den 50% war ja dann von mir Wunschinterpretation. ;-)

Ich bin hier sehr bei der Wahl eingeschränkt, da ich den Vorgaben des Kunden und dessen Konzern-IT unterlegen bin.
Das ich überhaupt an den VM-Parametern rumspielen darf ist ein Wunder. Auf 64bit VM umsteigen geht auf keinen Fall, da brauche ich nicht mal nachfragen. Auf Server VM umstellen kann ich nicht sagen, müsste ich beweisen das es was bringt.
Ich werde den Heap dann erstmal auf 1 oder 2 GByte hoch setzen, das sollte ggü. dem Default-Wert was bringen. Auch wenn ich bis jetzt nicht verstehe, warum Java eine Grenze will... Gibt es dazu im Web eine Erklärung?


----------



## artchi (15. Jul 2016)

Beim Versuch -Xmx2048m zu reservieren, gab es einen Error:
_15.07.2016  13:41:26.167 INFO: OUT > Error occurred during initialization of VM
15.07.2016  13:41:26.167 INFO: OUT > Could not reserve enough space for 2097152KB object heap_

1 GB waren kein Problem. Kann die Client VM keine 2 GB?


----------



## nvidia (15. Jul 2016)

Ja das theoretische Limit der 32-Bit Variante liegt bei 4GB. Auf 32-Bit Systemen bekommt man mit  der 32-Bit Version nur so max 1.4-1.6 GB hin, das liegt aber an Windows, das teilt den Adressraum IMHO in 2GB User/ 2GB Kernel auf und die JVM braucht ja selbst auch noch Speicher. Ich glaube das ändert sich auch nicht wenn du die 32-Bit Version in einem 64Bit System laufen lässt, da das ja nicht nativ in einem 64-Bit Prozess läuft schlagen da sicher die selben Beschränkungen zu. Unter Linux bekommst du für einen 32-Bit Prozess unter 64-Bit auch nur knapp 3GB hin.

Ein anderes Problem könnte natürlich auch sein das du nicht so viel freien Speicher am Stück hast.

Und weshalb es ein Max gibt, ich nehme an das ist einfach bedingt durch die JVM, einerseits ist es gut da du so dem Hostsystem nicht alle Ressourcen abziehen kannst und andererseits ist es sicher besser für den GC wenn er weiß mit was er maximal arbeiten kann.


----------



## artchi (15. Jul 2016)

Ja, ich bin auf einem 64 Bit Windows mit 8 GB RAM. Dann ist also bei 2 GB für die komplette Java VM schluss. Und das die VM sich dann was davon nimmt und damit ca. 1,4 GB für den User übrig bleibt, klingt logisch.

Wenn die User irgendwann noch mehr Heap bräuchten, müsste man über eine 64 Bit JVM nachdenken.
Danke für die ganzen Infos. Hat mir weiter geholfen.


----------



## artchi (15. Jul 2016)

zur Info: 1280M ist auch gescheitert. Anscheinend kann die VM nur 1024M.


----------



## nvidia (15. Jul 2016)

Das liegt glaube ich dann nicht immer an der VM, vll. konnte er nicht so viel Speicher am Stück allokieren. Einfach mal das System neustarten und schauen ob es geht wenn noch kaum Anwendungen geladen/verwendet wurden. Also Kandidaten wie Outlook, Webbrowser, Eclipse etc. beenden. Bei mir bekomme ich so um die 1.3GB hin (Mininum auf ca 700MB und Maximum auf ca. 1280 MB).


----------



## Cromewell (15. Jul 2016)

Wenn du 64Bit Java benutzt, kannst du einiges mehr rausholen.


----------



## michaels (15. Jul 2016)

Das Limit unter 32bit ist in der Tat 2GB (vom Betriebssystem). Allerdings ist darin nicht nur der nutzbare Speicherplatz, sondern auch sonstiges Zeugs für den Prozess enthalten. Netto bleibt damit deutlich weniger übrig und das schwankt auch (meistens um 1,2G).
Unter 64bit Maschinen ist der mögliche Adressraum so groß, dass es keine Rolle spielt. Habe auf meinem 64bit System (Linux) gerade ein Testprogramm mit Xmx128g gestartet. War kein Problem auch wenn ich den Speicher gar nicht habe 

Also solltest du unter deinem Win 64 auch ein Java 64 installieren könntest du auch deutlich mehr Speicher verwenden.


----------



## JStein52 (15. Jul 2016)

nvidia hat gesagt.:


> und schauen ob es geht wenn noch kaum Anwendungen geladen/verwendet wurden. Also Kandidaten wie Outlook, Webbrowser, Eclipse etc. beenden.


Das sollte eigentlich darauf keinen Einfluss haben denn es geht um den Adressraum eines einzelnen Prozesses (der JVM). Vorausgesetzt die Auslagerungsdatei ist gross genug angelegt.  (ich habe keine Ahnung ob Windows diese bei Bedarf vergrössern würde) Auch Windows ist ein virtuelles Betriebssystem und fängt dann an zu swappen wenn der physikalische Speicher ausgeht. Es wird dann halt langsam wenn man den ganzen Speicher benutzt.


----------



## Harald123 (8. Mai 2021)

Man kann durch einen cmd Befehl die heap size auslesen.

Ist es daher möglich diese durch einen cmd Befehl auch allgemein zu setzen? Ich meine nicht für eine bestimmte Anwendung.


----------



## kneitzel (8. Mai 2021)

Das ist ein 5 Jahre alter Thread. Wenn Du ein Problem hast, würde ich Dir raten, einen neuen Thread zu öffnen.

Ansonsten kannst Du die Optionen in die Umgebungsvariable _JAVA_OPTIONS schreiben. Die sollte bei jedem Java Start auch ausgelesen werden.


----------

