Wie ist der Java-Speicherpool aufgeteilt?

224

Ich überwache derzeit eine Java-Anwendung mit jconsole. Auf der Registerkarte Speicher können Sie wählen zwischen:

Heap Memory Usage
Non-Heap Memory Usage
Memory Pool “Eden Space”
Memory Pool “Survivor Space”
Memory Pool “Tenured Gen”
Memory Pool “Code Cache”
Memory Pool “Perm Gen”

Was ist der Unterschied zwischen ihnen ?

Dani Cricco
quelle
Angenommen, Sie verwenden das Sun JDK, finden Sie die beste Antwort in der Dokumentation: Optimieren der Garbage Collection (JDK 1.5) und der Garbage Collection-FAQ (JDK 1.4)
kdgregory

Antworten:

327

Heapspeicher

Der Heapspeicher ist der Laufzeitdatenbereich, aus dem die Java-VM Speicher für alle Klasseninstanzen und Arrays zuweist. Der Heap kann eine feste oder variable Größe haben. Der Garbage Collector ist ein automatisches Speicherverwaltungssystem, das Heapspeicher für Objekte zurückgewinnt.

  • Eden Space : Der Pool, aus dem der Speicher zunächst für die meisten Objekte zugewiesen wird.

  • Survivor Space : Der Pool mit Objekten, die die Speicherbereinigung des Eden Space überlebt haben.

  • Tenured Generation oder Old Gen : Der Pool, der Objekte enthält, die seit einiger Zeit im Überlebensraum existieren.

Nicht-Heap-Speicher

Nicht-Heap-Speicher enthält einen Methodenbereich, der von allen Threads und dem Speicher gemeinsam genutzt wird, die für die interne Verarbeitung oder Optimierung der Java-VM erforderlich sind. Es speichert klassenbezogene Strukturen wie einen Laufzeitkonstantenpool, Feld- und Methodendaten sowie den Code für Methoden und Konstruktoren. Der Methodenbereich ist logisch Teil des Heaps, aber abhängig von der Implementierung kann eine Java-VM ihn möglicherweise nicht durch Speicherbereinigung sammeln oder komprimieren. Wie der Heap-Speicher kann der Methodenbereich eine feste oder variable Größe haben. Der Speicher für den Methodenbereich muss nicht zusammenhängend sein.

  • Permanente Generierung : Der Pool, der alle reflektierenden Daten der virtuellen Maschine selbst enthält, z. B. Klassen- und Methodenobjekte. Bei Java-VMs, die die gemeinsame Nutzung von Klassendaten verwenden, ist diese Generation in schreibgeschützte und schreibgeschützte Bereiche unterteilt.

  • Code-Cache : Die HotSpot Java VM enthält auch einen Code-Cache, der Speicher enthält, der zum Kompilieren und Speichern von nativem Code verwendet wird.

Hier finden Sie eine Dokumentation zur Verwendung von Jconsole .

dfa
quelle
4
Ich bin mir nicht sicher, ob @dfa vollständig korrekt ist, da in der Java Virtual Machine-Spezifikation eindeutig angegeben ist: „Obwohl der Methodenbereich logisch Teil des Heaps ist, entscheiden sich einfache Implementierungen möglicherweise dafür, ihn weder zu sammeln noch zu komprimieren.“ Es ist jedoch klar, dass jconsole den Code-Cache und die permanente Generierung als Nicht-Heap anzeigt, was der Spezifikation zu widersprechen scheint. Kann jemand diesen Widerspruch näher erläutern?
James Bloom
@ JamesBloom - Ich habe mich das gleiche gefragt. Obwohl die grundlegende Definition angibt, welcher Speicherpool zu welchem ​​Typ gehört (Heap / Nicht-Heap), könnte sich der Status explizit ändern?
Umang Desai
2
Das Dokument, von dem dies halbwegs geklaut wurde: docs.intergral.com/pages/viewpage.action?pageId=22478944 Das Dokument enthält einige andere gute Informationen über die JVM, die einen Besuch wert sind
Steve Siebert
1
Trotz vieler positiver Stimmen ist es eigentlich keine so aussagekräftige Antwort. Was bedeutet zum Beispiel "Objekte, die die Müllabfuhr des Eden-Raums überlebt haben"? Werden diese Objekte nach dem Überleben von Eden in den Survivor Space verschoben oder wird ihr Space in Eden als Survivor Space betrachtet? Und was ist mit der Müllabfuhr in anderen Pools als dem Eden-Raum? Völlig nicht klar.
Mikhail Batcer
und nicht vergessen, Stapel (auf der Nicht-Haufen-Seite) :)
Zahnloser Seher
70

Das neue Schlüsselwort weist Speicher auf dem Java-Heap zu. Der Heap ist der Hauptspeicherpool, auf den die gesamte Anwendung zugreifen kann. Wenn nicht genügend Speicher für dieses Objekt verfügbar ist, versucht die JVM, mit einer Garbage Collection Speicher vom Heap zurückzugewinnen. Wenn immer noch nicht genügend Speicher verfügbar ist, wird ein OutOfMemoryError ausgelöst und die JVM wird beendet.

Der Heap ist in verschiedene Abschnitte unterteilt, die als Generationen bezeichnet werden. Wenn Objekte mehr Müllsammlungen überleben, werden sie in verschiedene Generationen befördert. Die älteren Generationen werden nicht so oft Müll gesammelt. Da sich diese Objekte bereits als längerlebig erwiesen haben, ist es weniger wahrscheinlich, dass sie als Müll gesammelt werden.

Wenn Objekte zum ersten Mal konstruiert werden, werden sie im Eden Space zugewiesen. Wenn sie eine Müllsammlung überleben, werden sie in den Survivor Space befördert. Sollten sie dort lange genug leben, werden sie der Tenured Generation zugeordnet. Diese Generation ist Müll, der viel seltener gesammelt wird.

Es gibt auch eine vierte Generation, die permanente Generation oder PermGen. Die Objekte, die sich hier befinden, können nicht durch Speicherbereinigung erfasst werden und enthalten normalerweise einen unveränderlichen Status, der für die Ausführung der JVM erforderlich ist, z. B. Klassendefinitionen und den String-Konstantenpool. Beachten Sie, dass der PermGen-Speicherplatz aus Java 8 entfernt werden soll und durch einen neuen Speicherplatz namens Metaspace ersetzt wird, der im nativen Speicher gespeichert wird. Referenz: http://www.programcreek.com/2013/04/jvm-run-time-data-areas/

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Pythoner
quelle
Das Diagramm sieht sehr selbsterklärend aus ... Gilt dies für jeden GC-Algorithmus? G1 haben unterschiedliche Sätze.
Venkateswara Rao
@ Python Ich denke, die Flagge in dunkelviolett sollte sein -XX:PermSizeund nicht so, -XX:MaxPermSizewie es bereits oben definiert ist.
Anurag
35

Mit Java8 enthält die Nicht-Heap-Region nicht mehr PermGen, sondern Metaspace, eine wichtige Änderung in Java8, die Speicherfehler mit Java beseitigen soll, da die Größe des Metaspace abhängig vom von jvm für Klassendaten benötigten Speicherplatz erhöht werden kann.

user2767149
quelle
1
Tatsächlich gibt es Metaspace und Klassenraum: docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/…
mrswadge
23

Der Java-Heapspeicher ist Teil des Speichers, der vom Betriebssystem der JVM zugewiesen wird.

Objekte befinden sich in einem Bereich, der als Heap bezeichnet wird. Der Heap wird beim Start der JVM erstellt und kann während der Ausführung der Anwendung vergrößert oder verkleinert werden. Wenn der Haufen voll ist, wird Müll gesammelt.

Geben Sie hier die Bildbeschreibung ein

Weitere Details zu Eden Space, Survivor Space, Tenured Space und Permanent Generation finden Sie in der folgenden SE-Frage:

Junge, Tenured und Perm Generation

PermGen wurde seit Java 8 durch Metaspace ersetzt.

In Bezug auf Ihre Fragen:

  1. Eden Space, Survivor Space und Tenured Space sind Teil des Heap-Speichers
  2. Metaspace und Code Cache sind Teil des Nicht-Heap-Speichers.

Codecache: Die Java Virtual Machine (JVM) generiert nativen Code und speichert ihn in einem Speicherbereich, der als Codecache bezeichnet wird. Die JVM generiert nativen Code aus verschiedenen Gründen, einschließlich für die dynamisch generierte Interpreterschleife, JNI-Stubs (Java Native Interface) und für Java-Methoden, die vom Just-in-Time-Compiler (JIT) in nativen Code kompiliert werden. Die JIT ist bei weitem der größte Benutzer des Codecaches.

Ravindra Babu
quelle