SCJP garbage collector frage

H2SO3-

Bekanntes Mitglied
Hi,

im Buch vom SCJP steht im Kapitel 3 folgende Frage mit Antowrt.
11. Given:
Java:
class Beta { }
class Alpha {
static Beta b1;
Beta b2;
}
public class Tester {
public static void main(String[] args) {
Beta b1 = new Beta(); Beta b2 = new Beta();
Alpha a1 = new Alpha(); Alpha a2 = new Alpha();
a1.b1 = b1;
a1.b2 = b1;
a2.b2 = b2;
a1 = null; b1 = null; b2 = null;
// do stuff
}
}
When line 16 is reached, how many objects will be eligible for garbage collection?
A. 0
B. 1
C. 2
D. 3
E. 4
F. 5
Answer:
® ✓ B is correct. It should be clear that there is still a reference to the object referred to by
a2, and that there is still a reference to the object referred to by a2.b2. What might be
less clear is that you can still access the other Beta object through the static variable
a2.b1—because it's static.
®˚ A, C, D, E, and F are incorrect based on the above. (Objective 7.4)

Laut meiner Meinung und auch nachdem was in der Antwort meiner meinung steht, müssten doch eigentlich 3 Objekte noch da sein. Also Antwort D richtig sein. Was meint ihr? Lese ich es falsch oder hat sich da ein fehler eingeschlichen?
 
Und welche 3 Objekte sollen das sein?Sehe nur noch a2 existieren...
a1, b1 und b2 werden ja auf null gesetzt und egal ob sie vorher woanders hin gespeichert wurden, wäre das ja nur die Referenz und somit wäre das Objekt trotzdem weg.

Denke Antwort B ist korrekt.
 
Lies mal die Frage richtig:
how many objects will be eligible for garbage collection?
B stimmt so schon.

--

NattleBet hat gesagt.:
a1, b1 und b2 werden ja auf null gesetzt und egal ob sie vorher woanders hin gespeichert wurden, wäre das ja nur die Referenz und somit wäre das Objekt trotzdem weg.
Genau eben nicht!
Die Variablen, welche hier auf
Code:
null
gesetzt werden, haben keinerlei Auswirkungen auf die eigentlichen Objekte! Erst, wenn ein Objekt gar nicht mehr erreichbar ist (und der GC ist da sehr klug, so dass zum Beispiel auch Circular References erkannt werden), kann es vom GC entfernt werden.

Auf
Code:
b1*
&
Code:
b2*
hat man eben über
Code:
a2*
noch Zugriff, weshalb nur ein Objekt,
Code:
a1*
, entfernt werden kann.

* Also die Objekte, welche über diese Variablen anfangs referenziert wurden.
 
Also Antwort D richtig sein. Was meint ihr? Lese ich es falsch oder hat sich da ein fehler eingeschlichen?


mit deiner frage bist du in guter gesellschaft. im forum java-ranch stapeln sich die posts zur frage 11. nun, um die frage 11 richtig zu verstehen, musst man zwischen referenzen und objekte unterscheiden. referenzen leben auf dem stack und objekte im heap. ein objekt ist für den gc nur dann wählbar, wenn es aus dem stack keine referenz hat, die auf ihn verweist. somit können hunderte von referenzen auf dem stack genullt werden, solange ein objekt noch eine referenz hat, kann es nicht weggeräumt werden. somit ist auch die korrekte antwort B, eben auch wegen "you can still access the other Beta object through the static variable a2.b1—because it's static.".
 
Zuletzt bearbeitet:
Kann es sein, dass in der Fragestellung die Zeile 16 die mit dem "// do stuff" war? So, wie die Frage hier gepostet wurde, müsste die Antwort m.E. eine andere sein, da in Zeile 16 (wenn man die überhaupt je "erreichen" könnte) alle lokalen Variablen, die in main deklariert worden sind, out-of-scope geraten wären...
 
dass die antwort im buch stimmt kann man auch empirisch belegen. ich habe den klassen Alpha und Beta einen konstruktor für den Namen hinzugefügt sowie die methode finalize() überschrieben. der gc sucht nämlich vor dem wegzuräumenden objekt nach dieser methode und falls sie existiert, wird sie ausgeführt. die methode gibt nur den namen des ojektes aus der konsole aus. das programm ist mit vorsicht zu geniessen, da es beim aufruf des gc keine garantie gibt, dass dieser auch tatsächlich objekte löscht. wie dem auch sein, auf meiner maschine läuft es gemäss der antwort b.


Code:
class Beta {
	private String name;
	public Beta(String n) {
		this.name = n;
	}
	
	public void finalize() {
		System.out.println("Der GC hat " + this.name + " weggeräumt.");
	}
}

class Alpha {
	static Beta b1;
	Beta b2;
	
	private String name;
	public Alpha(String n) {
		this.name = n;
	}
	
	public void finalize() {
		System.out.println("Der GC hat " + this.name + " weggeräumt.");
	}
}

public class Tester {
	public static void main(String[] args) {
		Beta b1 = new Beta("b1");

		Beta b2 = new Beta("b2");
		Alpha a1 = new Alpha("a1");
		Alpha a2 = new Alpha("a2");
		a1.b1 = b1;
		a1.b2 = b1;
		a2.b2 = b2;
		a1 = null;
		b1 = null;
		b2 = null;
		Runtime rc = Runtime.getRuntime();
		rc.gc();
	}
}
 
danke erstmal für die reichhaltigen Antworten 🙂
Aber so ganz ist es mir immer noch nicht klar.

Am Ende des programmes gibt es doch noch 3 Objekte. Nähmlich einmal a2. Da jedoch b1 und b2 noch eine referenz in a2 haben, sind sie bisher noch nicht zerstört. Wenn nun auch auf a2 keine referenz mehr ist, können doch alle 3 Objekte zerstört werden. Wieso zerstört der GC nun nur a2 und nicht auch b1 und b2??
 
Objekt b2 wird durch das Objekt a2 im Attribut b2 festgehalten.
Objekt b1 wird zuerst nur durch Objekt a1 referenziert wurden, da es aber statisch ist, bekommt jedes Objekt den gleichen Wert.
Die Objekte b1 und b2 behalten also noch Referenzen in den Attributen von Objekt a2.
 
Ja das ist klar. Aber dadurch müssten doch auch nach der zeile

Java:
a1 = null; b1 = null; b2 = null;

immer noch die 3 Objekte a2, b1, b2 da sein. Schließlich kann ich immer noch auf alle drei zugreifen.
Warum ist also nur noch 1 Objekt für den GC da?
 
Ja das ist klar. Aber dadurch müssten doch auch nach der zeile

Java:
a1 = null; b1 = null; b2 = null;

immer noch die 3 Objekte a2, b1, b2 da sein. Schließlich kann ich immer noch auf alle drei zugreifen.
Warum ist also nur noch 1 Objekt für den GC da?

Das soll wohl eher heißen, wieviel Objekte vom GC entsorgt werden können.
In der Frage heißt es ja garbage collection nicht garbage collector
 
Ja das ist klar. Aber dadurch müssten doch auch nach der zeile

Java:
a1 = null; b1 = null; b2 = null;

immer noch die 3 Objekte a2, b1, b2 da sein.


sind sie ja auch.

Warum ist also nur noch 1 Objekt für den GC da?


weil a1 das einzige objekt ist, auf welches keine referenz mehr existiert. somit ist dieses objekt unerreichbar resp. verloren und kann weggeräumt werden.
 
Ja aber wenn a1 weggeräumt ist, sind auch die letzten referenzen zu b1 und b2 weg. Somit können doch nun auch die weg. Klar zuerst muss a1 weg, aber direkt danach können auch b1 und b2 ab in den müll. Oder?
 
Nein, b2 wird von a2 referenziert und b1 wird von der Klasse Alpha referenziert(static!).
Es verwirrt natürlich dass da steht a1.b1 = b1; und nicht Alpha.b1 = b1;
 

Zurück
Oben