it-swarm.com.de

Java startet nicht - Es konnte nicht genügend Platz für den Objekthaufen reserviert werden

Hintergrund

Wir haben einen Pool von ungefähr 20 Linux Blades. Einige führen Suse aus, andere Redhat. ALL share NAS Speicherplatz, der die folgenden 3 Ordner enthält:

  • / NAS/app/Java - Ein Symlink, der auf eine Installation eines Java JDK. Derzeit Version 1.5.0_10 verweist
  • / NAS/app/lib - Ein Symlink, der auf eine Version unserer Anwendung verweist.
  • / NAS/data - Verzeichnis, in das unsere Ausgabe geschrieben wird

Alle unsere Computer verfügen über 2 Prozessoren (Hyperthreading) mit 4 GB physischem Speicher und 4 GB Swap-Speicher. Wir begrenzen die Anzahl der 'Jobs', die jeder Rechner zu einem bestimmten Zeitpunkt verarbeiten kann, auf 6 (diese Anzahl muss wahrscheinlich geändert werden, aber das ist noch nicht das aktuelle Problem, also ignorieren Sie es bitte vorerst).

Einige unserer Jobs haben eine maximale Heap-Größe von 512 MB, andere eine maximale Heap-Größe von 2048 MB. Wiederum stellen wir fest, dass wir unseren verfügbaren Speicherplatz überschreiten könnten, wenn 6 Jobs auf demselben Computer mit der Heap-Größe 2048 gestartet würden, aber unseres Wissens ist dies noch nicht geschehen.

Das Problem

Hin und wieder schlägt ein Job mit der folgenden Meldung sofort fehl:

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Früher haben wir zu viele Jobs gleichzeitig auf demselben Computer ausgeführt. Das Problem ist selten genug aufgetreten ( VIELLEICHT einmal im Monat), dass wir es einfach neu starten und alles in Ordnung wäre.

Das Problem ist in letzter Zeit viel schlimmer geworden. Alle unsere Jobs, die eine maximale Heap-Größe von 2048 m erfordern, schlagen fast jedes Mal sofort fehl und müssen vor Abschluss mehrmals neu gestartet werden.

Wir sind zu einzelnen Maschinen gegangen und haben versucht, sie manuell auszuführen, mit demselben Ergebnis.

Debuggen

Es stellt sich heraus, dass das Problem nur für unsere SuSE-Boxen besteht. Der Grund, warum es häufiger passiert ist, ist, dass wir mehr Maschinen hinzugefügt haben, und die neuen sind SuSE.

'cat/proc/version' auf den SuSE-Boxen gibt uns:

Linux version 2.6.5-7.244-bigsmp ([email protected]) (gcc version 3.3.3 (SuSE Linux)) #1 SMP Mon Dec 12 18:32:25 UTC 2005

'cat/proc/version' auf den RedHat-Boxen geben uns:

Linux version 2.4.21-32.0.1.ELsmp ([email protected]) (gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-52)) #1 SMP Tue May 17 17:52:23 EDT 2005

'uname -a' gibt uns Folgendes für BEIDE Maschinentypen:

UTC 2005 i686 i686 i386 GNU/Linux

Auf dem Computer werden keine Jobs ausgeführt, und keine anderen Prozesse belegen viel Arbeitsspeicher. Alle derzeit ausgeführten Prozesse möglicherweise verwenden insgesamt 100 MB.

'top' zeigt derzeit Folgendes:

Mem:   4146528k total,  3536360k used,   610168k free,   132136k buffers
Swap:  4194288k total,        0k used,  4194288k free,  3283908k cached

'vmstat' zeigt derzeit Folgendes an:

procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r  b   swpd   free   buff  cache   si   so    bi    bo   in    cs us sy id wa
0  0      0 610292 132136 3283908    0    0     0     2   26    15  0  0 100  0

Wenn wir einen Job mit der folgenden Befehlszeile starten (Max. Heap von 1850 MB), fängt er gut an:

Java/bin/Java -Xmx1850M -cp helloworld.jar HelloWorld
Hello World

Wenn wir die maximale Größe des Heapspeichers auf 1875 MB erhöhen, schlägt dies fehl:

Java/bin/Java -Xmx1875M -cp helloworld.jar HelloWorld
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Es ist ziemlich klar, dass der aktuell verwendete Speicher für das Puffern/Zwischenspeichern verwendet wird, und deshalb wird so wenig als "frei" angezeigt. Was nicht klar ist, warum es eine magische 1850-MB-Linie gibt, in der etwas Höheres Java kann nicht beginnen.

Für Erklärungen wäre ich sehr dankbar.

49
Randyaa

Sie verwenden ein 32-Bit-Betriebssystem, sodass die Gesamtgröße dadurch begrenzt wird. Andere Antworten haben dies ausführlicher behandelt, so dass ich vermeiden werde, ihre Informationen zu wiederholen.

Ein Verhalten, das ich kürzlich bei unseren Servern festgestellt habe, ist das Angeben einer maximalen Heap-Größe mit -Xmx ohne Angabe einer minimalen Heap-Größe mit -Xms würde dazu führen, dass Javas Server VM sofort versucht, den gesamten für die maximale Heap-Größe erforderlichen Speicher zuzuweisen. Und wenn die App diese Heap-Größe erreicht, ist das die Speicherkapazität Aber es ist gut möglich, dass Ihre Apps mit vergleichsweise kleinen Heaps beginnen und möglicherweise zu einem späteren Zeitpunkt einen größeren Heap benötigen. Wenn Sie zusätzlich die minimale Heap-Größe angeben, können Sie Ihren Heap starten Die App startet mit einem kleineren Haufen und vergrößert diesen Haufen nach und nach.

All dies wird Ihnen nicht helfen, Ihre maximale Heap-Größe zu erhöhen, aber ich dachte, es könnte helfen, also ...

21
Jon Bright

Wie in anderen Antworten vorgeschlagen, liegt das Problem an der Erschöpfung des virtuellen Adressraums. Ein 32-Bit-Linux-Userspace-Programm ist normalerweise auf 3 GB AS beschränkt. Die verbleibenden 1 GB werden vom Kernel verwendet (Begründung: Da es sich bei den obersten 1 GB um eine kernelfeste Zuordnung handelt, ist es nicht erforderlich, die Seitentabelle zu berühren, wenn Syscalls bereitgestellt werden).

RHEL-Kernel implementieren jedoch den sogenannten 4-GB-/4-GB-Split, bei dem den Anwendern der gesamte 4-GB-AS zu einem geringen Laufzeitaufwand zur Verfügung steht (der Kernel befindet sich in einem separaten virtuellen 4-GB-AS).

15
Luca Tettamanti

Das Ausführen eines 32-Bit-Betriebssystems ist ein Fehler. Sie sollten auf jeden Fall zum frühestmöglichen Zeitpunkt ein Upgrade durchführen.

Ich weiß nicht, ob Java erfordert, dass sich der Heap in einem einzigen zusammenhängenden Block befindet, aber wenn dies der Fall ist, klingt es wie eine große Herausforderung, nach 1,8 GB Heap auf einer 32-Bit-Box zu fragen. Sie gehen davon aus, dass fast die Hälfte des Adressraums zum Zeitpunkt des Starts von JVM frei ist.

Abhängig davon, welche anderen Bibliotheken zu diesem Zeitpunkt geladen sind, ist dies möglicherweise nicht der Fall. Bibliotheken können Speicher nach Belieben zuweisen, sodass der Adressraum so fragmentiert werden kann, dass 1,8 G nicht in einem Block verfügbar sind.

Unter Linux 32-Bit ist ohnehin nur ein maximaler 3G-Adressraum verfügbar. Bibliotheken und die JVM selbst verwenden zunächst einige davon.

8
MarkR

Bei 32-Bit-Servern scheint es eine JVM-Beschränkung zu geben, die nicht überwunden werden kann (es sei denn, Sie finden eine spezielle 32-Bit-JVM, die keine Beschränkung von 2 GB oder weniger vorsieht).

Dieser Thread auf der Serverseite enthält weitere Details, darunter mehrere Personen, die verschiedene JVMs auf 32-Bit-Architekturen getestet haben. IBMs JVM scheint 100 MB mehr zu erlauben, aber das bringt Ihnen nicht wirklich das, was Sie wollen.

http://www.theserverside.com/discussions/thread.tss?thread_id=26347

Die "echte" Lösung besteht darin, einen 64-Bit-Server mit einer 64-Bit-JVM zu verwenden, um Heaps zu erhalten, die größer als 2 GB pro Prozess sind. Es ist jedoch wichtig, auch die Auswirkungen einer Erhöhung der Adressgröße (nicht nur des adressierbaren Bereichs) mithilfe einer 64-Bit-JVM zu berücksichtigen. Bei der Verarbeitung mit weniger als 4 GB Arbeitsspeicher treten wahrscheinlich Leistungs- und Speichereinbußen auf.

Denkanstöße: Benötigen diese Jobs wirklich 2 GB Arbeitsspeicher? Gibt es eine Möglichkeit, die Jobs so zu ändern, dass sie innerhalb von 1,8 GB ausgeführt werden können, sodass dieses Limit kein Problem darstellt?

4
Brion

Ich habe zwei Anwendungen geschrieben, eine mittelgroße und eine ziemlich kleine. Ich würde das mittelgroße (unter Linux, Centos) ohne Argumente starten (Java-Server), und es würde gut laufen. Als ich dann die kleinere App mit "Java-Client" startete, wurde mir mitgeteilt, dass sie nicht genug Speicherplatz reservieren konnte und nicht ausgeführt werden konnte. Ich habe experimentiert und die -Xms und -Xmx beide mit 10m benutzt, und beide liefen ohne Beanstandung ... Go figure!

3
murf

ulimit maximale Speichergröße und virtueller Speicher auf unbegrenzt gesetzt?

3
Andrew

Ich habe den Arbeitsspeicher einer Maschine von 2 GB auf 4 GB aktualisiert und sofort den Fehler erhalten:

$ Java -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Das Problem war das ulimit, das ich auf 1GB für den adressierbaren Raum eingestellt hatte. Die Erhöhung auf 2 GB löste das Problem.

-Xms und -Xmx hatten keine Auswirkung.

Sieht aus wie Java versucht, Speicher im Verhältnis zum verfügbaren Speicher abzurufen, und schlägt fehl, wenn dies nicht möglich ist.

2
Penz

Sie müssen sich mit der Aktualisierung Ihres Betriebssystems und von Java befassen. Java 5.0 ist EOL, aber wenn Sie nicht auf Java 6 aktualisieren können, können Sie den neuesten Patch Level 22 verwenden!

32-Bit-Windows ist auf ~ 1,3 GB beschränkt, Sie sollten also das Maximum auf 1,8 einstellen. Hinweis: Dies ist ein Problem mit dem kontinuierlichen Speicher. Wenn Ihr System ausgeführt wird, kann der Speicherbereich fragmentiert werden. Es überrascht mich also nicht, dass Sie dieses Problem haben.

Ein 64-Bit-Betriebssystem hat dieses Problem nicht, da es über viel mehr virtuellen Speicherplatz verfügt. Sie müssen nicht einmal auf eine 64-Bit-Version von Java aktualisieren, um dies zu nutzen.

Übrigens kann 32-Bit-Version von Java 5.0 nach meiner Erfahrung schneller sein als 64-Bit-Version von Java 5.0. Erst viele Jahre später war Java 6 Update 10 für 64-Bit schneller.

2
Peter Lawrey

Ich habe vor kurzem dieses Problem konfrontiert. Ich habe 3 Java Anwendungen, die mit 1024m oder 1280m Heap-Größe beginnen. Java) prüft den verfügbaren Speicherplatz im Swap und ob nicht genügend Speicher verfügbar ist , der jvm geht ab.

Um das Problem zu beheben, musste ich mehrere Programme beenden, denen eine große Menge an virtuellem Speicher zugewiesen war.

Ich lief auf x86-64 Linux mit einem 64-Bit-JVM.

2
codeDr

Durchzuführende Schritte .... zur Behebung des Fehlers, der während der Initialisierung von VM Konnte nicht genügend Speicherplatz für den Objektheap reservieren Konnte die Java= virtuelle Maschine nicht erstellen .

Schritt 1: Reduzieren Sie den Arbeitsspeicher, den Sie früher verwendet haben. Java -Xms128m -Xmx512m -cp simple.jar

schritt 2: Entfernen Sie den RAM einige Zeit von der Hauptplatine, stecken Sie ihn ein und starten Sie ihn neu *, um den blockierenden Heap-Speicher freizugeben. Java -Xms512m -Xmx1024m -cp simple.jar

Hoffe, es wird jetzt gut funktionieren ... :-)

2

Das ist vielleicht ein bisschen abseits der Strecke, aber es gibt zwei Dinge, die einem in den Sinn kommen. In beiden folgenden Fällen wird davon ausgegangen, dass Sie eine 32-Bit-Version von Linux verwenden.

Es gibt eine Beschränkung der Prozessgröße unter Linux, die sich anscheinend unter CentOS auf 2,5 GB beläuft und im Kernel konfiguriert ist (d. H. Eine Neukompilierung zum Ändern). Wenn Sie den gesamten JVM-Code und den Permgen-Speicherplatz sowie alle anderen JVM-Bibliotheken addiert haben, könnte dies zu Problemen führen.

Das zweite, was mir aufgefallen ist, ist, dass Ihnen möglicherweise der Adressraum ausgeht. Klingt komisch, wie ich weiß. Beim Ausführen von Glassfish mit einem 1,5-GB-Heap ist ein Fehler aufgetreten, da das Betriebssystem nicht genügend Adressraum für den neu erstellten Prozess zuordnen konnte, obwohl 12 GB Speicher in der Box vorhanden waren. Möglicherweise ist hier etwas Ähnliches im Gange.

Ich fürchte, die einzigen Lösungen für die beiden oben genannten, bei denen ein Upgrade auf einen 64-Bit-Kernel erforderlich ist.

Hoffe, das ist von Nutzen.

2
Gareth Davis

Ich verwende SOA env, Verringerte Xmx von 1024 auf 768 in setSOADomainENV.cmd hat das Problem behoben.

REM set DEFAULT_MEM_ARGS=-Xms512m -Xmx1024m
set DEFAULT_MEM_ARGS=-Xms512m -Xmx768m
1
Kelvin

Angesichts der Tatsache, dass keiner der anderen Vorschläge funktioniert hat (einschließlich vieler Vorschläge, die ich mir selbst gemacht habe), können Sie versuchen, folgende Schritte auszuführen, um die Fehlerbehebung zu vereinfachen:

sysctl -a

Prüfen Sie, ob es auf den Maschinen SuSE und RedHat Unterschiede gibt. Ich vermute, die Standardkonfigurationen unterscheiden sich zwischen diesen beiden Distributionen, die dies verursachen.

1
Jack Leow

Was ist die JVM verwendet? Ich weiß, dass BEA JRockit bei maximaler Heap-Größe 1850 MB nicht überschreitet. Es schlägt nicht fehl, warnt aber den Benutzer, dass es nicht mehr als 1850 MB verwenden wird.

Ich weiß nicht, warum es eine solche Grenze gibt, aber ich weiß, dass es sie für BEA JRockit gibt.

Freundliche Grüße.

1
Johan Guiheneuf