Java Heap Space vs Stack – Speicherallokation in Java

Vor einiger Zeit habe ich ein paar Beiträge über Java Garbage Collection und Java ist By-Value übergeben geschrieben. Danach erhielt ich viele E-Mails, um Java Heap Space, Java Stack Memory, Speicherzuweisung in Java zu erklären und was die Unterschiede zwischen ihnen sind. Sie werden viele Verweise auf den Heap- und Stack-Speicher in Java, Java EE-Büchern und Tutorials sehen, aber kaum eine vollständige Erklärung dessen, was Heap- und Stack-Speicher in Bezug auf ein Programm sind.

Java Heap Space

Java-Heap-Speicher wird vom Java-Laufzeitumgebung verwendet, um Speicher für Objekte und JRE-Klassen zuzuweisen. Immer wenn wir ein Objekt erstellen, wird es im Heap-Speicher erstellt. Die Garbage Collection läuft im Heap-Speicher, um den Speicher freizugeben, der von Objekten verwendet wird, die keine Referenz haben. Jedes im Heap-Speicher erstellte Objekt hat globalen Zugriff und kann von überall in der Anwendung referenziert werden.

Java Stack Memory

Java Stack-Speicher wird für die Ausführung eines Threads verwendet. Sie enthalten methodenspezifische Werte, die kurzlebig sind, sowie Verweise auf andere Objekte im Heap, die von der Methode referenziert werden. Der Stack-Speicher wird immer nach dem Last-In-First-Out (LIFO)-Prinzip referenziert. Wenn eine Methode aufgerufen wird, wird im Stack-Speicher ein neuer Block für die Methode erstellt, um lokale primitive Werte und Verweise auf andere Objekte in der Methode zu halten. Sobald die Methode endet, wird der Block nicht mehr verwendet und steht für die nächste Methode zur Verfügung. Die Größe des Stack-Speichers ist im Vergleich zum Heap-Speicher sehr gering.

Heap- und Stack-Speicher in Java-Programmen

Lassen Sie uns die Verwendung von Heap- und Stack-Speicher anhand eines einfachen Programms verstehen.

package com.journaldev.test;

public class Memory {

	public static void main(String[] args) { // Line 1
		int i=1; // Line 2
		Object obj = new Object(); // Line 3
		Memory mem = new Memory(); // Line 4
		mem.foo(obj); // Line 5
	} // Line 9

	private void foo(Object param) { // Line 6
		String str = param.toString(); //// Line 7
		System.out.println(str);
	} // Line 8

}

Das folgende Bild zeigt den Stack- und Heap-Speicher im Zusammenhang mit dem oben genannten Programm und wie sie zur Speicherung von primitiven Werten, Objekten und Verweisvariablen verwendet werden. Lassen Sie uns die Schritte der Programmausführung durchgehen.

  • Sobald wir das Programm ausführen, lädt es alle Laufzeitklassen in den Heap-Speicher. Wenn die main()-Methode in Zeile 1 gefunden wird, erstellt die Java-Runtime Stack-Speicher, der vom main()-Methode-Thread verwendet wird.
  • Wir erstellen eine primitive lokale Variable in Zeile 2, daher wird sie im Stapelspeicher der Methode main() erstellt und gespeichert.
  • Da wir ein Objekt in der 3. Zeile erstellen, wird es im Heap-Speicher erstellt und der Stapelspeicher enthält die Referenz dafür. Ein ähnlicher Prozess findet statt, wenn wir das Memory-Objekt in der 4. Zeile erstellen.
  • Wenn wir nun die Methode foo() in der 5. Zeile aufrufen, wird ein Block oben im Stapel erstellt, der von der Methode foo() verwendet wird. Da Java wertbasiert ist, wird in dem foo()-Stapelblock in der 6. Zeile eine neue Referenz auf das Objekt erstellt.
  • A string is created in the 7th line, it goes in the String Pool in the heap space and a reference is created in the foo() stack space for it.
  • Die Methode foo() wird in der 8. Zeile beendet, zu diesem Zeitpunkt wird der im Stapel für foo() allokierte Speicherblock frei.
  • In Zeile 9 wird die Methode main() beendet und der für die Methode main() erstellte Stapelspeicher wird zerstört. Außerdem endet das Programm an dieser Stelle, daher gibt die Java-Runtime alle Speicher frei und beendet die Ausführung des Programms.

Unterschied zwischen Java-Heap-Speicher und Stapelspeicher

Auf der Grundlage der obigen Erläuterungen können wir leicht die folgenden Unterschiede zwischen Heap- und Stapelspeicher feststellen.

  1. Der Heap-Speicher wird von allen Teilen der Anwendung verwendet, während der Stapelspeicher nur von einem Ausführungsthread verwendet wird.
  2. Wenn ein Objekt erstellt wird, wird es immer im Heap-Speicher gespeichert und der Stapelspeicher enthält die Referenz dazu. Der Stapelspeicher enthält nur lokale primitive Variablen und Referenzvariablen zu Objekten im Heap-Speicher.
  3. Objekte, die im Heap gespeichert sind, sind global zugänglich, während auf den Stapelspeicher nicht von anderen Threads zugegriffen werden kann.
  4. Die Speicherverwaltung im Stapel erfolgt nach dem LIFO-Prinzip, während sie im Heap-Speicher komplexer ist, da er global verwendet wird. Der Heap-Speicher ist in Young-Generation, Old-Generation usw. unterteilt, weitere Details finden sich unter Java Garbage Collection.
  5. Der Stapelspeicher ist kurzlebig, während der Heap-Speicher vom Start bis zum Ende der Programmausführung besteht.
  6. Wir können die JVM-Optionen -Xms und -Xmx verwenden, um die Startgröße und maximale Größe des Heap-Speichers zu definieren. Wir können -Xss verwenden, um die Größe des Stapelspeichers zu definieren.
  7. Wenn der Stapelspeicher voll ist, wirft die Java-Laufzeit eine java.lang.StackOverFlowError, während wenn der Heap-Speicher voll ist, wirft es einen java.lang.OutOfMemoryError: Java Heap Space Fehler.
  8. Die Größe des Stapelspeichers ist im Vergleich zum Heap-Speicher sehr gering. Aufgrund der Einfachheit der Speicherzuweisung (LIFO) ist der Stapelspeicher im Vergleich zum Heap-Speicher sehr schnell.

Das ist alles für Java Heap Space vs Stack Memory in Bezug auf Java-Anwendungen. Ich hoffe, das klärt Ihre Zweifel bezüglich der Speicherzuweisung, wenn ein Java-Programm ausgeführt wird.

Hier ist die Übersetzung: https://de.wikipedia.org/wiki/Java_Memory_Model.

Source:
https://www.digitalocean.com/community/tutorials/java-heap-space-vs-stack-memory