Java Speicherverwaltung, Objektreferenzen und mehr
Auf Basis von
In Java (und sehr vielen anderen Programmiersprachen) ist die Nutzung des Hauptspeichers (RAM) in 4 Kategorien geteilt: Code-Segment (kompiliertes Programm), Data Segment (Statische Daten), Stack (Stapel) und Heap (Haufen)
+-----------+ | | | code | (fixed size) | | +-----------+ | | | data | (fixed size) | | +-----------+ | stack | | growth +-----------+ v | | | free | | | +-----------+ ^ | heap | | growth +-----------+
Wir betrachten hier Stack und Heap:
Der Heap ist der flexible, frei (und langsamer) nutzbare Bereich, der Stack hingegen ist der für den Ablauf des Programms streng organisierte und damit schneller zugreifbare Bereich.
Beim Laufen eines Programms wird (vereinfacht) – immer beginnend bei der main
-Methode (die von BlueJ "versteckt" angelegt wird, wenn nicht im Sourcecode vorhanden) – direkt "gearbeitet" und/oder ein Objekt angelegt und daran eine andere Methode aufgerufen.
Im Stack wird der Speicherplatz für Aufruf, Parameter und Rückgabewerte sowie lokale Variable bereitgestellt und beim Aufruf einer weiteren Methode "stapelt" sich der für diese benötigte Specherbereich über dem der bisher offenen Methoden.
In dieser aufgerufenen Methode finden ihrerseits sehr oft Aufrufe weiterer Methoden statt, wodurch sich je gerade offener Methode ein weiteres "Paket" auf diesen Stapel legt. Sobald eine Methode unter Bereitstellung ihres Rückgabewertes beendet ist, wird sie (bzw. ihre Daten) vom Stapel entfernt.
Dieses Auf- und wieder Abbauen des Stapels findet ununterbrochen während des Programmlaufes statt, bis das Programm durch vollständigen "Abbau" des Stapels beendet ist.
Der Heap hingegen enthält zur Programm-Laufzeit sämtliche gerade existierenden Objekte und (in Vergleich wenige) weitere Daten. Erste wenn eine Methode läuft, werden ihre Daten in den hochstruktuierten Stack geholt.
Für neue Objekte – Instanzierung mit z.B. new Person("Evi", 1999)
) – wird vom Java-Laufzeitsystem genauso viel Heap-Speicher angefordert, wie für das Ablegen der Instanzvariablen (primitive Datentypen und Objektreferenzen) benötigt wird (bei Objektreferenzen nur 32 Bit für die Adresse, nicht für das separat zu instanzierende Objekt).
Hier ein kurzes Java-Programm, um die Nutzung von Stack und Heap zu erläutern:
package com.journaldev.test;
public class Memory {
public static void main(String[] args) { (1)
int i=1; (2)
Object obj = new Object(); (3)
Memory mem = new Memory(); (4)
mem.foo(obj); (5)
} (9)
private void foo(Object param) { (6)
String str = param.toString(); (7)
System.out.println(str);
} (8)
}
in Arbeit ...
-
All Runtime classes are loaded into the Heap Space when the program is run.
-
Java Runtime creates Stack memory to be used by main() method thread when it is found at line 1.
-
At line 2, a primitive local variable is created, which is stored in the Stack memory of main() method.
-
Since an Object is created at line 3, it’s created in Heap memory and the reference for it is stored in Stack memory.
-
At line 4, a similar process occurs when a Memory object is created.
-
When foo() method is called at line 5, a block in the top of the Stack is created for it.
-
Since Java is pass by value, a new reference to Object is created in the foo() stack block in line 6.
-
At line 7, a string is created, which goes in the String Pool in the Heap space, while a reference for it is created in the foo() stack space.
-
At line 8, foo() method is terminated, and the memory block allocated for it in the Stack is freed.
-
Finally, at line 9, main() method terminates, and the Stack memory created for it is destroyed. Because the program ends at this line, Java Runtime frees all the memory and ends the execution of the program.
Key Differences
Java Heap Space is used throughout the application, but Stack is only used for the method — or methods — currently running. The Heap Space contains all objects are created, but Stack contains any reference to those objects. Objects stored in the Heap can be accessed throughout the application. Primitive local variables are only accessed the Stack Memory blocks that contain their methods. Memory allocation in the Heap Space is accessed through a complex, young-generation, old-generation system. Stack is accessed through a last-in, first-out (LIFO) memory allocation system. Heap Space exists as long as the application runs and is larger than Stack, which is temporary, but faster.
Linksammlung TODO: https://de.wikipedia.org/wiki/Java_Virtual_Machine [Java Virtual Machine – Wikipedia] ... 2023-08-06 https://en.wikipedia.org/wiki/Java_virtual_machine [Java virtual machine - Wikipedia] ... 2023-08-06