Java Stack vs. Heap: Een Praktische Gids voor Geheugentoewijzing
Wat Is Stack Geheugen?
In Java is de stack een aaneengesloten geheugenregio die methode-aanroepframes, lokale variabelen en referentievariabelen bevat. Elke keer dat een methode aangeroepen wordt, wordt een nieuw frame op de stack gezet. Stack geheugen is georganiseerd in Last-In, First-Out (LIFO) volgorde, wat betekent dat de meest recente aanroep de eerste is die verwijderd wordt wanneer de methode terugkeert.
Wat Is Heap Geheugen?
De heap is het gebied waar Java-objecten worden aangemaakt. Het bevat alle instanties van klassen en, optioneel, referentievariabelen die naar die objecten wijzen. In tegenstelling tot de stack, is de heap niet gebonden aan de levensduur van een enkele methode-aanroep, waardoor objecten kunnen voortbestaan buiten de scope waarin ze zijn aangemaakt.
Geheugentoewijzing in Java
Geheugentoewijzing in Java verwijst naar het proces van het reserveren van virtueel geheugen voor programma-data. Variabelen worden niet bij declaratie toegewezen; in plaats daarvan wordt een referentie aangemaakt. Wanneer de new operator gebruikt wordt, reserveert de JVM ruimte op de heap voor het object.
Java verdeelt het geheugen in vier verschillende secties voor efficiënt beheer:
- Heap
- Stack
- Code (Bytecode)
- Statisch (Klassedata)
- De Code sectie bevat de gecompileerde bytecode.
- De Stack bevat methode-frames, lokale variabelen en referentievariabelen.
- De Heap slaat objecten op en,'occasioneel, referentievariabelen.
- De Statische sectie bewaart statische velden en methodes.
Lokale vs. Instantievariabelen
Instantievariabelen worden gedeclareerd binnen een klasse maar buiten elke methode:
class Student {
int num; // instantievariabele
public void showData() {}
}
Lokale variabelen worden gedeclareerd binnen een methode (of als methodeparameters):
public void sum(int a) {
int x = a + 3; // a en x zijn lokale variabelen
}
Stack vs. Heap in Actie
Laten we een voorbeeld doorlopen om te illustreren hoe de stack en heap interageren tijdens methode-aanroepen.
Stel dat de main methode m1() aanroept:
public void m1() {
int x = 20;
}
Een frame voor m1 wordt op de stack gezet. De lokale variabele x wordt in dit frame opgeslagen.
Wanneer m1 m2(int b) aanroept, wordt een nieuw frame bovenop m1's frame gezet:
public void m2(int b) {
boolean c;
}
Op dezelfde manier roept m2 m3() aan, wat nog een frame creëert:
Binnen m3 wordt een Account object geïnstantieerd op de heap, terwijl de referentie ref op de stack leeft:
class Account {
int p;
int q;
}
public void m3() {
Account ref = new Account(); // extra code
}
De referentievariabele ref wordt aangemaakt in m3's stack frame en wijst naar het heap-gealloceerde Account object.
Wanneer m3 voltooid is, wordt het stack frame afgebroken, waardoor het Account object zonder referenties overblijft. Het wordt in aanmerking genomen voor garbage collection.
Hetzelfde proces herhaalt zich voor m2 en m1, wat uiteindelijk de controle teruggeeft aan main.
Objectreferenties als Instantievariabelen
Beschouw een klasse A die een referentie bevat naar een instantie van B:
public static void main(String[] args) {
A parent = new A(); // extra code
}
class A {
B child = new B();
int e;
}
class B {
int c;
int d;
}
Hier wordt de child referentie opgeslagen op de heap als onderdeel van het A object, en wijst naar zijn eigen B instantie.
Belangrijkste Punten
- Elke methode-aanroep creëert een nieuw frame op de stack.
- Lokale variabelen residieren op de stack; instantievariabelen zijn op de heap.
- Referentievariabelen worden op de stack opgeslagen maar wijzen naar heap-objecten.
- Wanneer een stack frame afgebroken wordt, worden de lokale en referentievariabelen verwijdert, en worden verwaarloosde heap-objecten in aanmerking genomen voor garbage collection.
Java
- Java-variabelen en literals: een uitgebreide gids
- Java klassen en objecten: een praktische gids
- Java abstracte klassen en methoden: een uitgebreide gids
- Java geneste en inner classes meesteren: typen, voorbeelden en best practices
- Java throw vs throws: Exception Handling meesteren met praktische voorbeelden
- Java Annotatie typen: uitgebreide gids over voorgedefinieerde, aangepaste en meta annotaties
- Java Autoboxing en Unboxing: Praktische voorbeelden en best practices
- Java String Vervanging beheersen: replace(), replaceAll() en replaceFirst() uitgelegd
- Java Method Overriding: Superclass-gedrag aanpassen
- Java 10: Heap toewijzen op NV-DIMM met -XX:AllocateHeapAt
- Java 8 Method References: Uitgebreide gids