Skip to main content

Java Objekte leben auf dem Heap

Java hat eine interne Speicherverwaltung.
Eigentlich ist es nicht nur eine. Es sind mehrere.
 
Uns interessieren nur zwei.
Methoden und lokale Variablen werden auf dem Stack verwaltet.
Und die Speicherverwaltung für Java Objekte und den Instanzvariablen findet auf dem Heap statt.
 
Ja wieso braucht Java eigentlich zwei Speichersysteme?
 
Es ist ganz einfach.
Java Objekte werden an einem anderen Ort, gespeichert als Methoden oder lokale Variablen.

Denn ein Objekt umfasst meistens mehrere Variable.
Es ist somit ein ganz anderer Speicherbedarf notwendig.
Außerdem muss ein Objekt, unter Umständen, auch länger im Programm gehalten werden.
 
Okay und warum solltest du das wissen?

Stell dir vor, du schreibst ein Java Spiel.
Irgendeins bei dem du irgendwelche Vögel auf dem Bildschirm abschießen musst.
Jeder Vogel, welcher durch den Spieler getroffen wurde, verschwindet vom Bildschirm.
Und dafür kommt ein neuer Vogel.
 
Was meinst du?
Wenn der Vogel vom Bildschirm verschwindet, verschwindet er dann auch aus dem Speicher?
Kann es sein, dass sich der Speicher nach und nach füllt mit Vogel-Objekten, welche niemand braucht.
 
Und um diese Dinge zu vermeiden, solltest du wissen, wie Java Objekte speicherintern verwaltet werden.

Java Objekte existieren auf dem Heap

In einem anderen Beitrag habe ich schon einmal geschrieben, dass Methoden und lokale Variablen auf dem Stack gestapelt werden.
 
Für Java Objekte existiert eine andere Speicherverwaltung.
Und diese nennt sich Heap.
 
Bleiben wir beim Vogelspiel.
Im nachfolgenden Java Code habe ich, innerhalb der main Methode, ein „Vogelobjekt“ angelegt.


public class VogelSpiel {
	int vogelGroesse; // Größe in Pixel
 
 
	public static void main(String[] args) {
		VogelSpiel vogelEins = new VogelSpiel();
	}
}

Wir haben bereits geklärt, dass die main Methode auf dem Stack liegt.
Und lokale Variablen liegen ebenfalls auf dem Stack.
 
Aber in diesem Fall existiert noch ein Objekt.

Was ist mit diesem?
 
Ganz einfach.
Die Referenzvariable ist samt Main-Methode auf dem Stack.
Und diese verweist schließlich nur auf das Objekt.
 
Das eigentliche Objekt liegt auf dem Heap.

Java Objekte verweis Heap
 
Und nun?
Auf dem Heap wird dieses Objekt solange bereitgestellt, bis es nicht mehr gebraucht oder zerstört wird.
 

Wenn du Java Objekte aus dem Heap entfernen willst, schenke ihnen einfach keine Beachtung mehr.

Hört sich blöd an – Aber so ist es.
 
Im Vogelspiel wird es doch so sein:

  • Erster Vogel taucht auf.
  • Dieser wird abgeschossen.
  • Und dann kommt der nächste Vogel ins Spiel.

Das heißt.
Ich lege einen zweites „Vogelobjekt“ und eine zweite Referenzvariable an.


public class VogelSpiel {
	int vogelGroesse; // Größe in Pixel
 
 
	public static void main(String[] args) {
		VogelSpiel vogelEins = new VogelSpiel(); //Erstes Vogelobjekt
		VogelSpiel vogelZwei = new VogelSpiel(); //Zweites Objekt
 
	}
}
  • Die Referenzvariable „vogelEins“ verweist auf das erste Objekt.
  • Die Referenzvariable „vogelZwei“ verweist auf das zweite Objekt.

Java Objekte Zwei Verweise

Wenn der erste Vogel abgeschossen wurde, brauch ich diesen doch nicht mehr.
 
Und jetzt kann ich den Zeiger bzw. den Verweis auf das erste Objekt entfernen.
Dazu muss ich der Variablen „vogelEins“ den Wert der Variablen „vogelZwei“ zuweisen.
 
Zur Errinnerung:
Referenzvariablen speichern keine Zahl oder Ähnliches.
Sie speichern lediglich den Verweis auf ein Java Objekt.
 
Und wenn du der Variablen „vogelEins“ jetzt den Wert aus „vogelZwei“ zuweist, dann switchst du den Verweis um.
Java Objekte switch

Und Objekt 1 steht nun ohne Referenzvariable da.
Stattdessen verweisen jetzt zwei Variablen auf das zweite Objekt.
 
Und so würde das Ganze im Java Code aussehen:


public class VogelSpiel {
	int vogelGroesse; // Größe in Pixel
 
 
	public static void main(String[] args) {
		VogelSpiel vogelEins = new VogelSpiel(); //Erstes Vogelobjekt
		VogelSpiel vogelZwei = new VogelSpiel(); //Zweites Objekt
		vogelEins=vogelZwei; //Wert der Variablen vogelZwei wird vogelEins zugewiesen
	}
}

Okay, was passiert nun mit dem ersten Objekt?
 

Für Java Objekte ohne Verweis ist der Garbage Collector zuständig.

Und der Garbage Collector ist die Müllabfuhr von Java.
 
Dieses Feature hat nur eine Aufgabe.
Es sucht im ganzen Programm nach Objekten ohne Verweis und löscht diese aus dem Speicher.
Es würde somit das Objekt 1 vom Heap löschen und somit wieder Speicher freigeben.
 
Wie aktivierst du nun die Garbage Collection?
Gar nicht.
Das ganze passiert automatisch.
 
Der Garbage Collector erkennt automatisch:

  • „Ah, Objekt 1 vom Typ „VogelSpiel“ hat keinen Verweis.
  • Also schick ich das Ding ab in den Müll.
  • Und gebe wertvollen Speicher für neue Objekte frei.“

Cool, oder?
Aber was passiert mit den ganzen Instanzvariablen?
 

Instanzvariablen existieren solange, wie die dazu gehörigen Java Objekte.

Ich setze alles noch einmal auf Anfang.
 
Wir haben zwei Vogelobjekte, mit Referenzvariablen „vogelEins“ und „vogelZwei“.
 
VogelEins hat eine Größe von 22 Pixel.
VogelZwei hat eine Größe von 17 Pixel.

Java Objekte Instanzvariablen

Somit hat jedes Objekt seine eigene individuelle Instanzvariable.
 
Und so sieht der Code dazu aus.


public class VogelSpiel {
	int vogelGroesse; // Größe in Pixel
 
 
	public static void main(String[] args) {
		VogelSpiel vogelEins = new VogelSpiel(); //Erstes Vogelobjekt
		VogelSpiel vogelZwei = new VogelSpiel(); //Zweites Objekt
 
		vogelEins.vogelGroesse=22; // Vogel Eins mit 22px
		vogelZwei.vogelGroesse=17; // Vogel zwei mit 17 px
	}
}

Wenn ich jetzt den Zeiger von „vogelEins“ auf „vogelZwei“ switche, dann übertragen sich auch alle Werte der Instanzvariablen.
 
Aus Kontrollzwecken habe ich ein paar Bildschirmanzeigen in den Java Code einfließen lassen.
Klicke einmal „Run“ und du siehst das Ergebnis.


public class VogelSpiel {
	int vogelGroesse; // Größe in Pixel
 
 
	public static void main(String[] args) {
		VogelSpiel vogelEins = new VogelSpiel(); //Erstes Vogelobjekt
		System.out.println("VogelEins wurde angelegt");
		VogelSpiel vogelZwei = new VogelSpiel(); //Zweites Objekt
		System.out.println("VogelZwei wurde angelegt");
 
		vogelEins.vogelGroesse=22; // Vogel Eins mit 22px
		System.out.println("VogelEins hat eine Größe von: "+ vogelEins.vogelGroesse);
		vogelZwei.vogelGroesse=17; // Vogel zwei mit 17 px
		System.out.println("VogelZwei hat eine Größe von: "+ vogelZwei.vogelGroesse);
		 
		vogelEins=vogelZwei;
		System.out.println("VogelEins wurde auf VogelZwei umgeswicht");
		 
		System.out.println("Jetzt hat VogelEins die Größe: "+vogelEins.vogelGroesse);
	}
}

Und wenn die Java Objekte ohne Verweis zerstört werden.
Dann zerstört der Garbage Collector auch die dazu gehörigen Instanzvariablen.
 
Denn diese werden durch das Um-switchen ebenfalls überflüssig.

Java-Objekte-Instanzvariablen-Verweise

So und wenn du jetzt so ein Vogelspiel anlegst und dann circa 1000 Vogelobjekte durch den Bildschirm fliegen.
Und du durch eine Methode immer schön die Verweise abänderst, dann hältst du immer nur ein Objekt im Spiel.
 
Alle anderen Objekte werden durch den fehlenden Verweis zerstört.
 
Okay, du hast zwar nur ein Objekt.
Dennoch existieren irgendwann 1.000 Referenzvariablen.
 
Ist doch auch blöd, oder?
Lass uns das noch ändern.
 

Eine Referenzvariable kann auch auf verschiedene Objekte verweisen.

Ich stell mir das Ganze so vor:

  • Erstes Vogelobjekt wird mit einer Referenzvariablen angelegt.
  • Sobald das erste Objekt nicht mehr gebraucht wird, wird ein zweites Objekt angelegt.
    Jetzt wird aber keine zweite Referenzvariable angelegt.
  • Stattdessen verweist die ursprüngliche Variable vom ersten Java Objekt auf das zweite.
    Somit wird das erste Objekt unbrauchbar und es ist Futter für den Garbage Collector.

Java Objekte Garbage Collector

Besser, oder?
 
Und so geht’s.
Und zwar legst du immer wieder neue Objekte an.
Du legst aber keine neuen Referenzvariablen für diese Java Objekte an.


public class VogelSpiel {
	int vogelGroesse; // Größe in Pixel
 
 
	public static void main(String[] args) {
		VogelSpiel vogelEins = new VogelSpiel(); //Erstes Vogelobjekt
		vogelEins.vogelGroesse=22;
		System.out.println("Neuer Vogel mit "+vogelEins.vogelGroesse+" im Spiel.");
		System.out.println("Vogel tot");
		 
		vogelEins=new VogelSpiel(); //Zweites Vogelobjekt ohne neue Referenzvariable
		vogelEins.vogelGroesse=17;
		System.out.println("Neuer Vogel mit "+vogelEins.vogelGroesse+" im Spiel.");
		System.out.println("Vogel tot");
		 
		vogelEins=new VogelSpiel(); //Drittes Vogelobjekt ohne neue Referenzvariable
		vogelEins.vogelGroesse=5;
		System.out.println("Neuer Vogel mit "+vogelEins.vogelGroesse+" im Spiel.");
		System.out.println("Vogel tot");
	}
}

Somit brauchst du eine Variable, welche auf das aktuelle Objekt zeigt.
 
Alle Objekte, welche unbrauchbar sind, besitzen keinen Verweis.
Und diese werden vom Heap geschafft und es steht immer neuer Speicher zur Verfügung.
 
Zusammenfassung:

  • Java unterscheidet zwei wesentliche Speichersysteme.
  • Java Objekte werden im sogenannten Heap gespeichert.
    Instanzvariablen gehören zu den Objekten und werden ebenfalls dort verwaltet.
  • Methoden und deren lokalen Variablen befinden sich im Stack-Speicher.
  • Wenn du in der main-Methode ein Objekt anlegst, befindet sich die Referenzvariable im Stack und das Objekt im Heap.
  • Um den Heap immer wieder zu bereinigen, musst du nur die entsprechende Referenzvariable um-switchen.
    Alle Java Objekte ohne Verweis werden durch den Garbage Collector automatisch aus dem Heap entfernt.

Ähnliche Beiträge

Java Exklusives Oder – So nutzt du den Xor Operator

Java exklusives oder

In diesem Beitrag möchte ich dir den Xor Operator von Java vorstellen. Dieser Operator wird auch als ausschließendes oder exklusives Oder bezeichnet. Ein Beispiel: Was wilst du heute zum Mittag essen: Fleisch oder Fisch? Auf diese Frage gibt es nur eine Antwort. Es ist entweder Fisch oder Fleisch. Niemals beides. Das Eine schließt das andere […]

So kannst du ein Java Programm starten und Argumente übergeben

Um ein Java Programm starten zu können, benötigst du immer die main-Methode. Das Programm startet immer genau an dieser Stelle. Alle lokalen Variablen, welche du in der Main Methode anlegst, kannst du dann im Programm nutzen. Auch alle Methoden, welche du innerhalb des Methodenrumpfes der main-Methode aufrust, werden ausgeführt. Was ist aber vor der main-Methode. […]

So kannst du Instanzen in Java Klassen zählen

Wie kannst du die Instanzen der Java Klassen zählen? Ganz einfach. Am besten ist es, wir bleiben beim Einführungsbeispiel zu den Java Klassen. Und ich wähle die Klasse „Monster“. Um es einfach zu halten, soll auch der Programmstart durch die Klasse erfolgen. Die Klasse bietet somit eine main-Methode an.

Lassen wir Java rechnen – Die Rechenoperationen für Variablen

Java rechnen

Ich liebe Mathe. In der Biographie „Der Mann, der die Zahlen liebte“, stellt Paul Hoffmann das Mathematikgenie Paul Erdös vor. Erdös war eines der größten Genies des 20 Jahrhunderts. Er arbeitete mit zahlreichen Wissenschaftlern zusammen und verfasste durchschnittlich mehr Publikationen im Jahr, als andere Mathematiker im ganzen Leben. Da Erdös sich mit sehr vielen Theoremen […]

Java Übung 31: Speichere deine Würfe im Array

Java Übung Array Würfelspiel

In dieser Java Übung soll ein Würfelspiel simuliert werden. Lege eine Klasse namens, Würfelspiel an. Diese Klasse enthält eine statische Methode, namens würfeln(). Diese Methode erwartet einen Parameter vom Datentyp Integer, namens „anzahlWuerfe“. Diese Variable/Parameter repräsentiert die Anzahl der Würfe. Nachdem der Methode die Anzahl der Würfe übergeben wurde, soll die Methode Zufallszahlen zwischen 1 […]

Java for Schleifen schachteln – So funktioniert es

Java For Schleifen schachteln

Diese Situation kennst du doch auch…. Du stehst an der Haltestelle und wartest auf den Bus. Dein Blick fällt auf die Uhr.   Oder du wartest an der Ecke auf deinen Freund oder Kollegen. Immer wieder schaust du auf deine Uhr.   Sie ist kaum noch wegzudenken. Die mobile Taschenuhr.   Lange Zeit wurde die […]

So verwendest du Inkrement und Dekrement Operatoren in deinen Java Programmen

Java Operatoren

In diesem Beitrag geht es um Java Operatoren. Ich möchte dir gern zwei neue Operatoren vorstellen. Diese nennen sich Inkrement und Dekrement. Ja was heißt das? Inkrementieren bedeutet eine schrittweise Erhöhung einer Zahl. Und dementsprechend bedeutet Dekrementieren: Die schrittweise Verminderung einer Zahl. Wozu brauchst du das? Stell dir vor. Du bekommst eine Liste mit Namen […]

3 Möglichkeiten um Vererbung von Java Klassen zu verhindern, zu verbieten oder ausschließen

Java Vererbung verhindern

Die ganze Java Vererbung für bestimmte Klassen ausschließen bzw. verhindern oder verbieten. Was soll das? Für bestimmte Java Klassen soll die Vererbung ausgeschlossen werden. Es soll also verhindert werden, dass Elternklassen – Kindklassen bekommen können. Klingt ein bisschen wie Verhütung, oder? Denn wie auch im echten Leben, können Kinder zu kleinen Tyrannen werden. Sie bedienen […]

So nutzt du das Java Keyword public

Java Keyword public

Java Programme bestehen aus Java Klassen. Und der Zugriff auf eine Java Klasse sollte nach außen immer gewährleistet sein. Was bedeutet das? Du solltest in jeder Klasse die Möglichkeit haben, ein Objekt einer anderen Klasse anzulegen. Gerade durch diese Möglichkeit macht doch das ganze Klassenkonstrukt erst Sinn.