views:

474

answers:

6

Give the following code:

class A {
    Boolean b;
    A easyMethod(A a){
        a = null;
        return a;
    }
    public static void main(String [] args){
        A a1 = new A();
        A a2 = new A();
        A a3 = new A();
        a3 = a1.easyMethod(a2);
        a1 = null;
        // Some other code 
    }
}

The question is how many objects are eligible for garbage collection right before // Some other code.

Then correct answer is (at least that's the interviewer answer): 2 - the Boolean b because it's a wrapper and a1 .

Can you please me explain me why a2 and a3 aren't being garbage collected ?

LATER EDIT:

  • Ok, I think I get it now. It was a bit confusing at first, but now i am sure the interviewer was wrong. My initial mistake was that at first I didn't consider that Java is pass by value only, so it's impossible to make a2 null from inside a function that take "a2" as a parameter, because that a2 is actually a copy of a2.
  • The part with the Boolean b was indeed quite obvious.

Thanks for an answer, I will send some interview feedback after that :).

+8  A: 

Provided a1.go(a2) is actually meant to be a1.easyMethod(a2), the answer is indeed 2, but not the ones you listed. As Bozho rightly pointed out, b is not initialized, so it doesn't refer to any object. The two objects eligible for garbage collection at the point of the comment are the ones originally referenced by a1 and a3.

a1 is obviously nulled out, and a3 is reassigned to the return value of a1.easyMethod(a2), which is null. However, a2 is not affected by the method call, as Java is pass by value, so only a copy of the reference a2 is passed to the method. Even though the copy is set to null, that does not affect the value of the original a2.

Péter Török
+1 For mentioning that Java is pass by value. It just never passes Objects, just their references. I understand why it is confusing to some, but I think it's something every (Java) developer should know.
glowcoder
@glowcoder, yeah, I learnt it the hard way, here on SO :-)
Péter Török
+10  A: 

Assuming go is supposed to be easyMethod it works like this

class A {
    Boolean b;
    A easyMethod(A a){
        a = null; // the reference to a2 was passed in, but is set to null
                  // a2 is not set to null - this copy of a reference is!
        return a; // null is returned
    }
    public static void main(String [] args){
        A a1 = new A(); // 1 obj
        A a2 = new A(); // 2 obj
        A a3 = new A(); // 3 obj
        a3 = a1.go(a2); // a3 set to null and flagged for GC - see above for why
        a1 = null; // so far, a1 and a3 have been set to null and flagged
        // Some other code 
    }
}

Two objects are eligible for garbage collection (a1 and a3). b is not because it's only a reference to null. No Boolean was ever made.

glowcoder
and the two objects are a1 and a3
willcodejavaforfood
Ah yes, I only have it my comment. Thanks @wcJff
glowcoder
*were* a1 and a3...
Justin K
For the sake of correctness I would change "Two objects get garbage collected" to "Two objects are *eligible* to be garbage collected"
matt b
@Justin I lol'd. :) @matt true - my comment reflects this point, but my summary does not. Fixed.
glowcoder
I think it does not matter of `A.go()` is `A.easyMethod()` or not. In regards to GC, the object referred to by a3 is orphaned by the call and thus eligible for GC. Unless more code is given `b` is dead code.
Sean Farrell
@Sean you're absolutely right about a3 being orphaned, and about b being dead code. :-)
glowcoder
+3  A: 

First of all the interviewer is wrong about the Boolean -- there is no such object created by this code so there's nothing to be garbage collected.

It is incorrect to speak of variables like b and a2 as being garbage collected. Objects are garbage-collected, not variables. If an in-scope variable references an object, then it cannot be garbage-collected. Simplistically, it's only when an an object is no longer referenced by any variable that it can be garbage collected.

So we have three instances of A being created in this code. They start out referenced by a1 etc. but since variable references change I'll refer to the object instances as A1, A2, and A3. Since you haven't shown a definition of the go method I'm going to assume it's meant to be a call to easyMethod.

Since the variable a1 is reassigned to null, nothing is pointing to instance A1, so it can be garbage-collected.

Since the variable a2 is never reassigned (the assignment in easyMethod does not affect the original variable), instance A2 cannot be garbage-collected.

Since easyMethod always returns null and a3 is assigned the result of that method, nothing is pointing to instance A3, so it can also be garbage-collected.

Dave Costa
+3  A: 

Can you please me explain me why a2 and a3 aren't being garbage collected ?

Because a2 and a3 are not objects. They are variables. Variables are not collectable for the simple reason that they are not allocatable.

John
+1 Snarky, but right.
Justin K
+3  A: 

For a2's original referant it actually completely depends on what happens in "some other code". If "some other code" doesn't use a2 or a3, then the original a2 object is eligible for garbage collection.

That's because the runtime doesn't have to care about lexical scope. It just needs to know that an object can never be referenced again. Therefore, if "some other code" doesn't utilize a2 or a3, the object they point to can never be referenced again and so is already available for garbage collection.

Mark Peters
At the point of // some other code . there is only a2 who can be used. a1 and a3 is null.
mathk
The objects initially referenced by `a1` and `a3` have no way of being referenced again at the point of "some other code", and so they can be GC'ed. The same can't be said of the object referenced by `a2`. This doesn't depend at all on later code.
Justin Ardini
@Justin: I never meant to imply otherwise, but I understand the source of your confusion and so have edited it to hopefully reflect better what I was trying to say.
Mark Peters
@Mark: Thanks, much clearer! I had interpreted your phrasing "completely depends" as meaning the code snippet has no effect on whether any of the objects would be GC'ed.
Justin Ardini
Yeah, it goes back to the necessary vs sufficient conditions. Not referencing a1/a2/a3 in "some other code" was a sufficient condition for GC eligibility, but certainly not necessary, as indeed a1/a3's original referents were GC eligible either way. "Completely depends" obviously doesn't convey that properly.
Mark Peters
+1  A: 

Your question is quite confuse.

A garbage collector work on object not on binding. So when you say that a2 is eligible for GC it mean nothing. You should say the object hold in a2 at line N is eligible for GC at the line N+M.

In your example you only have 3 object being instantiate. It is the first create A and the last create A instance that are eligible for GC.

mathk