views:

86

answers:

4
class CardBoard {
  Short story = 200;
  CardBoard go(CardBoard cb) {
    cb = null;
    return cb;
  }
  public static void main(String[] args) {
    CardBoard c1 = new CardBoard();
    CardBoard c2 = new CardBoard();
    CardBoard c3 = c1.go(c2);
     System.out.println("c3 value : "+c3);
     c1 = null;
     System.out.println("c1 value : "+c1);
     System.out.println("c2 value : "+c2);
    // do Stuff
  } 
}

This is an example from the SCJP6 mock exam. The question states: When // doStuff is reached, how many objects are eligible for GC? And the answer is (2 objects) because: Only one CardBoard object (c1) is eligible, but it has an associated Short wrapper object that is also eligible.

When I execute the code, it looks like c3 also points to null... so I would have said that 3 objects are eligible for GC.

Can someone please guide me through the logic of this code.

+1  A: 

c3 never points to any object, it is always a null variable. Therefore, object c3 is not eligible for GC

vodkhang
A: 

In your code only c1 and story (Short) contained within c1 are eligible for GC. i.e. 2 objects.

c3 is never referencing any object as go() method returns null.

c2 is not eligilble for GC. As in Java method arguments are passed by value. and when go method is called c2 keeps pointing to object , though in go method passed variable is assigned null.

YoK
Incorrect. The c2 reference is never assigned `null`. The `go` method is a trick to see if the reader understands that Java does NOT use pass-by-reference.
Stephen C
at `// doStuff`, `c2` still references a `CardBoard` so is **not** eligible for gc. The 2 objects are `c1` and the `Short` within it as Vineet's answer says.
mikej
Thanks I was already updating my answer with info which i quoted wrong :(.
YoK
+8  A: 

The object c3 is originally null, so there is no question of recollecting it, for it never existed in the first place. The garbage collector is meant to scavenge objects that actually exist on the heap.

Among the rest, the reference to c2 is never discarded, and hence it will not be reclaimed. Although it appears that c2 is nullified in the statement CardBoard c3 = c1.go(c2);, this is not the case. The reference to c2 has been passed in by value and although the reference is nullified, there is an existing reference to the object in the main method. Hence it will not be reclaimed.

This leaves us with c1, that has been explicitly nullified and hence eligible for collection. However, c1 also contains a reference to the Short variable story, which does not have any inbound references from any other object. This results in two objects being eligible for scavenging - one CardBoard object and the embedded Short object.

Vineet Reynolds
or, to put it very simply: in that code, there's only two cases of the `new` keyword, and they are executed only once (they're in the main method and not in an iteration). So by definition this code only creates two object. How could it ever collect more?
Joeri Hendrickx
@Joeri, no doubt that you're correct. But it is not easy to deduce the number of objects eligible for collection, based on the number of created objects alone. Yes, it is a good indicator, but counting strong references is more important, and it is very easy to go wrong there by merely reading the code.
Vineet Reynolds
@Vineet Of course, I fully agree. It's just that in this case, the code is so extremely simple, you don't even need to look any further. Still a good exercise though.
Joeri Hendrickx
@Joeri `Short story = 200` creates an object without using `new` so in fact this code creates 4 objects, 2 of which are eligible for gc at doStuff and 2 of which are not.
mikej
@mikej Good point. Didn't notice that :)
Joeri Hendrickx
+2  A: 

CardBoard c1 = new CardBoard();

Creates a CardBoard instance and its Short instance. (2 objects) Assigns the CardBoard reference to c1.

CardBoard c2 = new CardBoard();

Creates another CardBoard instance and its Short instance. (2 more objects) Assigns the CardBoard reference to c2.

CardBoard c3 = c1.go(c2);

Assigns null to c3. (The go method is a trick to see if you understand Java argument passing semantics. If you think that Java uses pass-by-reference, you might incorrectly conclude that c2 is set to null by this call. In fact, c2 is unchanged.)

c1 = null;

Assigns null to c1. This renders the first CardBoard instance and its Short instance unreachable, and candidates for garbage collection.

The second CardBoard instance and its Short instance are still reachable.

Stephen C