wann wird der JVM-Heap vom Betriebssystem zugewiesen

wann wird der JVM-Heap vom Betriebssystem zugewiesen

Eines unserer SAP-Systeme (PI ABAP+JAVA-Stack) verursachte Leistungsprobleme. Die gesamten für die Maschine konfigurierten 64 GB werden beansprucht (und auch die 8 Kerne). Jeder vermutet den Java-Teil, aber ich denke, das ist anders.

Die Java-Serverknoten wurden mit einem Speicherfehler neu gestartet. Beim Betrachten der hprof-Dateien stellte ich fest, dass sie nur 1,2 G groß waren (Durchschnitt von 3 Serverknoten), obwohl für die Serverknoten 3 GB (sowohl Xms als auch Xmx) Heap konfiguriert sind. Diese Beobachtung führte zu den folgenden Zweifeln.

Ich habe gelesen, dass der JVM beim Start der gesamte Heap zugewiesen wird, wenn Xms und Xmx auf denselben Wert eingestellt sind. Wenn das der Fall ist, hätten die Serverknoten von Anfang an 3 GB Heap. Wenn ja, warum wird das nicht in der hprof-Datei angezeigt, oder wenn die hprof-Datei nur den Speicher enthält, der Objekten während der Laufzeit zugewiesen wurde, zeigt die Größe eindeutig an, dass der Heap-Speicher frei war (mehr als 50 %), also wie kommt es zu einem OOM-Fehler...!!..??

Ich weiß auch, dass Linux etwas macht, das als Speicherüberbelegung bezeichnet wird. D. h. Speicher wird nicht tatsächlich zugewiesen, wenn er angefordert wird, sondern wenn er tatsächlich verwendet wird. Trägt dies zur Ausnahme „Nicht genügend Speicher“ bei? Wenn beispielsweise die JVM startet, teilt ihr das Betriebssystem mit, dass Ihnen 3 GB Speicher zugewiesen wurden, verschiebt dies aber tatsächlich, bis es tatsächlich benötigt wird. Bis die JVM tatsächlich versucht, den Speicher Objekten zuzuweisen, haben andere Anwendungen den Speicher möglicherweise bereits erschöpft. Ist das möglich...??

Selbst wenn die Java-Knoten ein Speicherleck hätten, wäre es dann nicht auf die 3 GB des Heaps beschränkt? Wie kann es die gesamten 64 GB des physischen Speichers beanspruchen...???

Eine weitere Sache, die mir auffiel, war, dass der Swap-Speicher nur zu 50 % genutzt wurde.

Irgendein Licht ins Dunkel...!

Antwort1

SAP OSS hat sich ebenfalls mit dem Problem befasst. Heute habe ich die Antwort von ihnen erhalten. Meine Beobachtung war richtig. Java war nicht der Übeltäter. Der ABAP-Stack hatte ein Problem und gab keinen Speicher frei. Nach dem Neustart des ABAP-Arbeitsprozesses wurde der Speicher auf Betriebssystemebene freigegeben.

Aber ich würde auch gerne den hervorgehobenen Teil der Frage verstehen, z. B. ob eine solche Situation auftreten kann oder nicht, die zu JAVA-OOM-Fehlern führt...??..!!. Alle Informationen in dieser Hinsicht sind hilfreich.

Antwort2

Overcommit ist unter Linux im heuristischen Modus standardmäßig aktiviert. Das bedeutet, dass der Kernel Overcommit normalerweise zulässt. Das bedeutet, dass allen Prozessen, die es anfordern, mehr Speicher versprochen wird, als er tatsächlich liefern kann, in der Hoffnung, dass die Prozesse nie den gesamten Speicher gleichzeitig verwenden. Möglicherweise ist Overcommit auf Ihrem Server deaktiviert. Sie können dies überprüfen, indem Sie Folgendes ausführen:

$ cat /proc/sys/vm/overcommit_memory

Wenn der Wert 0 ist, wird die heuristische Übervergabe aktiviert.

Wenn die Situation eintritt, dass der tatsächliche Speicherverbrauch die Menge an RAM übersteigt, die das System bereitstellen kann, aktiviert der Kernel den OOM-Killer, der versucht, Prozesse zu beenden, um Speicher freizugeben. Normalerweise werden dabei die jüngsten Prozesse beendet, die große Mengen an RAM verbrauchen, aber Sie können sich nicht darauf verlassen. Es kann (und wird) Chaos verursachen. Sie können die Affinität von OOM ändern, um bestimmte Prozesse zu beenden, indem Sie /proc//oom_adj anpassen (zum Beispiel, wenn Sie eine Situation vermeiden möchten, in der OOM eine Datenbank oder einen anderen großen RAM-[Miss]brauch beendet).

Wenn Ihr System also in die OOM-Phase eintritt, könnte dies zur Folge haben, dass Java-Prozesse sofort beendet werden. In den beobachteten Java-Protokollen würde dies jedoch nicht zu der Meldung „Nicht genügend Arbeitsspeicher“ führen.

Wenn Sie sowohl Xmx als auch Xms auf denselben Wert setzen, wird eine Größenänderung des Heaps verhindert. Das bedeutet jedoch nicht, dass der Java-Prozess beim Start sofort den gesamten Speicher verwendet. Er weist so viel zu, wie er VIRT-Speicher benötigt, aber der residente Datensatz wächst nicht auf Xms an, sondern bleibt so klein wie nötig.

In Bezug auf virtuellen Speicher: Der Kernel verspricht (überbelegt) dem Java-Prozess so viel, wie er verlangt (Xmx + etwas mehr), aber der gesamte Speicher wird nicht sofort zugewiesen. Es wird nur die für die aktuellen Daten benötigte Menge zugewiesen, und Sie können sehen, wie viel, indem Sie die Größe des residenten Satzes beobachten (nicht ausgelagerter physischer Speicher, den eine Aufgabe verwendet hat). Um die VIRT- und RSS-Größen anzuzeigen, können Sie den folgenden Befehl ausführen:

$ ps aux | egrep '(^USER|java)'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tomcat   10229 21.5  9.1 6813688 548344 ?      Sl   09:01   1:10 ....java...

Höchstwahrscheinlich sind die von Ihnen beobachteten Fehler ein Hinweis darauf, dass dem unter dem Java Virtual Machine-Prozess ausgeführten Programm nicht genügend Heap-Speicherplatz zur Verfügung steht. Versuchen Sie es mit einer Erhöhung der Xmx-Einstellung und testen Sie Ihre App erneut.

verwandte Informationen