JVM-Speicherverwaltung

Einführung in die Java-Speicherverwaltung

In diesem Artikel werde ich mehr über die JVM-Speicherverwaltung innerhalb der Java Virtual Machine (JVM) erklären. Wenn Sie ein Java-Entwickler sind, ist das Verständnis der Java-Speicherverwaltung in JVM sehr hilfreich bei der Untersuchung von Leistungsproblemen im Zusammenhang mit Speicherlecks, Garbage Collection usw., die für Anwendungen in Produktionsqualität von entscheidender Bedeutung sind.

Im Folgenden finden Sie eine Liste der Segmente innerhalb der Java Virtual Machine (JVM) zum Speichern der für die Anwendungsausführung erforderlichen Laufzeitdaten. Am Ende dieses Tutorials werden Sie verstehen, wie JVM Speicher zuweist und welche wichtigen Befehle zum Senden von Anweisungen an JVM für die Speicherzuweisung gelten. Wenn Sie Fragen zu JVM haben oder mit Problemen wie einem Speicherverlust konfrontiert sind, posten Sie diese bitte im Kommentarbereich.

Im Folgenden sind die wichtigsten Speichersegmente innerhalb einer JVM aufgeführt:

  • Programmzähler (PC)-Register
  • Methodenbereich
  • Haufen
  • Java-Stack
  • Nativer Stack
  • JVM-Speicherzuweisung

    Programmzähler (PC)

    Einer der von der JVM zugewiesenen Speicherbereiche ist der Programmzähler (PC). In diesem Segment wird die Speicheradresse der aktuell ausgeführten Java Virtual Machine (JVM)-Anweisungen gespeichert. Jedes Mal, wenn ein neuer Thread erstellt wird, wird ein Programmzähler erstellt. Der Programmzähler enthält einen Zeiger auf die aktuellen Anweisungen, die im aktuellen Thread ausgeführt werden. Wenn es sich bei der aktuell ausführenden Methode um eine native Methode handelt, ist das Zählerregister undefiniert.

    Methodenbereich

    Methodenbereich innerhalb der JVM, der zum Speichern der Typ-/Klasseninformationen verwendet wird. Wenn Sie zum ersten Mal eine Java-Anwendung ausführen, versucht der Klassenlader, die Klassen zu laden, indem er den vollständig qualifizierten Namen jeder Klasse verwendet. Der Klassenlader liest die Klassendatei als Binärdatenstrom und speichert die Details im Methodenbereich. Der Methodenbereich ist auch für die Zuweisung des Speichers zum Speichern der Klassen-/statischen Variablen verantwortlich. Der Methodenbereich ist für alle Threads gleich und muss daher threadsicher gestaltet sein.

    Der Speicher des Methodenbereichs könnte auf dem eigenen Heap der JVM zugewiesen werden. Es liegt bei der Implementierungsentscheidung und wird nicht durch die Spezifikation vorgeschrieben. Der Methodenbereich kann auch durch Müll gesammelt werden. Wenn eine Klasse nicht mehr referenziert wird, kann eine JVM die Klasse entladen, um den vom Methodenbereich belegten Speicher auf ein Minimum zu beschränken.

    Im Folgenden finden Sie weitere Details, die im Methodenbereich gespeichert sind:

    Geben Sie Informationen ein

    Im Folgenden finden Sie eine Liste der im Methodenbereich gespeicherten Typinformationen:

    • Der vollständig qualifizierte Name des Typs
    • Der vollständig qualifizierte Name der direkten Superklasse des Typs (es sei denn, der Typ ist eine Schnittstelle oder Klasse java.lang.Object, die keine Superklasse hat)
    • Ob der Typ eine Klasse oder eine Schnittstelle ist oder nicht
    • Die Modifikatoren des Typs

    Der konstante Pool

    Ein Methodenbereich verfügt über einen Konstantenpool, in dem Literale wie String, Zahl usw. und symbolische Verweise auf Typen, Felder und Methoden gespeichert werden. Auf alle im Konstantenpool gespeicherten Daten wird über einen Index verwiesen, der einem Array ähnelt. Dieser Konstantenpool fungiert als zentraler Ort für die dynamische Verknüpfung von Java-Programmen.

    Feldinformationen

    Die folgenden Details zu Feldern werden im Methodenbereich gespeichert. Darüber hinaus speichert es auch die Reihenfolge, in der die Felder von der Klasse oder Schnittstelle deklariert werden, im Speicher.

    • Feldname
    • Feldtyp
    • Feldmodifikatoren

    Methodeninformationen

    Die folgenden Details zu Methoden werden im Methodenbereich gespeichert. Darüber hinaus speichert es auch die Reihenfolge, in der die Methoden von der Klasse oder Schnittstelle deklariert werden, im Speicher.

    • Methodenname
    • Methodenrückgabetyp oder ungültig
    • Die Anzahl der Parameter
    • Der Typ der Parameter in der Reihenfolge
    • Die Modifikatoren der Methode

    Java-Stack

    Der Java-Stack ist der Speicherbereich, der von den JVM-Threads zum Speichern der threadspezifischen Daten verwendet wird. Der Stapelspeicher wird nicht von allen Threads gemeinsam genutzt und wird für jeden Thread separat erstellt. Alle mit einer Methode verbundenen Daten wie lokale Variablen und Objektverweise auf den Heap werden im Stapelspeicher gespeichert. Immer wenn ein Thread eine neue Methode eingibt, wird im Stapelspeicher ein neuer Block namens Stapelrahmen erstellt, um die methodenspezifischen Details zu speichern. Wenn der Thread die Ausführung dieser Methode abschließt, wird der entsprechende Stapelrahmen aus dem Stapelspeicher verschoben. Der für den Stack zugewiesene Gesamtspeicher ist im Vergleich zum Heap-Speicher sehr gering.

    Wenn der aktuelle Stapelspeicher nicht ausreicht, um die Methodendaten zu speichern (dies passiert, wenn die Methode über eine rekursive Operation verfügt), führt JVM zu einem Fehler java.lang.StackOverflowError Fehler. Wenn Sie diesen Fehler erhalten, müssen Sie den Stapelspeicher vergrößern oder das Programm analysieren, ob es versehentlich rekursive Aufrufe verwendet. Auch tiefe Rekursionen können StackOverflow-Fehler verursachen.

    Wie kann der Stapelspeicher erhöht werden?

    Entwickler können die Stapelspeichergröße mithilfe von ändern -Xss Befehl. Diese Größe ist die Stapelgröße des einzelnen Threads. Das bedeutet, dass jedem Thread die gleiche Menge an Speicher für seine Vorgänge zugewiesen wird. Viele Herausgeber von Java Virtual Machine legen die Standardgröße des Aufrufstapels eines Threads auf 256 KB fest.

    Java-Heap

    Wenn Ihre Anwendung neue Objekte erstellt oder Arrays verwendet, werden alle Instanzen im Heap-Speicher der Java Virtual Machine (JVM) gespeichert. Heap ist der primäre Speicher innerhalb der JVM zum Speichern der Laufzeitdaten, auf die mehrere Threads zugreifen. Der Heap-Speicher ist der gemeinsame Speicher für alle Threads. Die im Heap gespeicherten Daten sind für alle Threads zugänglich, die auf der JVM ausgeführt werden.

    Wenn die maximale Größe des Heaps von der JVM genutzt wird, wird der Garbage Collector ausgelöst, um den Speicher von den nicht verwendeten Objekten im Heap zu beanspruchen. Beachten Sie, dass der Anwendungsentwickler keine Kontrolle über den Garbage Collector hat.

    Der Heap-Speicher besteht aus zwei logischen Teilen, die auf der Lebensdauer jedes Objekts basieren. Das erste ist Junge Generation und der zweite ist Alte Generation.

    Junge Generation:

    Der Heap-Speicher erstellt neue Objekte in dem Teil, der als junge Generation bezeichnet wird. Dieser Teil ist für die Speicherung der jungen Objekte vorgesehen, die von den Java-Anwendungen ganz neu erstellt werden.

    Alte Generation:

    Dies ist ein weiterer logischer Teil im Heap-Speicher zum Speichern der älteren Objekte. Wenn neue Objekte erstellt werden, die sich für einen bestimmten Zeitraum im Teil der jungen Generation befinden, werden diese Objekte danach in den Teil der alten Generation verschoben. Objekte, die einige Male aus dem Garbage Collector überstanden sind, werden zur alten Generation hochgestuft.

    Wenn der insgesamt zugewiesene Speicher nicht ausreicht, um die neuen Objekte zu speichern, löst JVM einen java.lang.OutOfMemoryError aus. Anwendungsentwickler können die Speicherzuweisung für den Heap innerhalb der JVM anpassen, indem sie die folgenden Parameter übergeben:

    JVM-Heap-Einstellungen:

    • -Xmx : Maximale zugewiesene Heap-Größe
    • -Xms : Anfänglich zugewiesene Heap-Größe
    • -Xmn : Größe der Speicherung von Objekten der jungen Generation im Heap. Dieser Parameter wird in den meisten Fällen nicht verwendet.

    JVM-Heap-Größe

    Nativer Methodenstapel

    Ähnlich wie beim Java-Stack gibt es einen Native Method Stack zum Speichern der Thread-Daten für native Methodenaufrufe. Dieser native Methodenstapel ist nur verfügbar, wenn die JVM die nativen Methodenaufrufe unterstützt. Andernfalls ist der native Methodenstapel nicht erforderlich. Die Speichergröße wird ähnlich wie bei allgemeinen JVM-Stacks wie fest oder dynamisch verwaltet. Dies wird pro Thread erstellt und kann nicht von allen Threads gemeinsam genutzt werden. Wenn der native Methodenstapel voll ist und nicht über genügend Speicher zum Speichern der neuen Daten verfügt, löst JVM entsprechend StackOverflowError oder OutOfMemoryError aus.

    Ich hoffe, dass dieses Tutorial gute Informationen über die JVM-Speicherzuweisung liefert. Wenn Sie Fragen haben, schreiben Sie diese bitte in den Kommentarbereich.

    Kommentar verfassen

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

    Nach oben scrollen