1

When the line containing "//doStuff" is reached, how many objects will be available for garbage collection ?

a. 0
b. 1
c. 2
d. 3
e. 4
f. 5
class Beta
{

}

class Alpha
{
    static Beta b1;
    Beta b2;
}

public class Tester
{
    public static void main(String[] args)
    {
        Alpha a1=new Alpha();
        Alpha a2=new Alpha();
        Beta b1= new Beta();
        Beta b2= new Beta();

        a1.b1=b1;
        a1.b2=b1;
        a2.b2=b2;

        a1=null;
        b1=null;
        b2=null;

        //doStuff
    }
}

Given answer : 1

I think the answer should be 2 because the objects assigned to both a1 and b1 are no longer accessible.

Vinayak
  • 13
  • 6
  • 6
    b1 is stored in the **static** field Alpha.b1. So it's still reachable. The question is tricky because although it's allowed, no responsible developer would ever use `a1.b1`. The good practice would be to use `Alpha.b1 = b1` – JB Nizet Aug 25 '19 at 13:26
  • i think a1 and b2 are eligible for garbage collection – prasad Aug 25 '19 at 14:46
  • 2
    @prasad - No. b2 is reachable as a2.b2. And a2 has not been nulled. – Stephen C Aug 25 '19 at 15:10
  • @StephenC yes you are correct then answer is only a1 – prasad Aug 25 '19 at 15:17
  • Only a1 is what? Unreachable? – Stephen C Aug 25 '19 at 15:20
  • @JBNizet Got it, thanks. Only the object pointed by a1 will be unreachable. Object pointed by b1 will still be reachable because we don't need Alpha object to access Alpha class's b1 field ; we can simply use Alpha.b1 to access it. – Vinayak Aug 25 '19 at 15:52

1 Answers1

3

Questions like this rarely make any sense. Usually, the asker (interviewer) has put a particular gotcha into the question and will consider any answer correct which identifies the gotcha, ignoring the other immanent flaws of the question.

Here, the gotcha is that the assignment a1.b1=b1; assigns to a static field, which keeps the reference alive, even when a1 gets assigned to null.

The fundamental flaw of the question “how many objects will be available for garbage collection?” is that we do not even know, how many objects exist. The JVM initialization and launcher startup code may have created an arbitrary number of temporary objects eligible to garbage collection when the main method has been entered and still eligible to garbage collection when reaching the specified point.

Even if we restrict the question to the artifacts visible in the code of the question, the given answer is wrong.

The Java® Language Specification states:

A reachable object is any object that can be accessed in any potential continuing computation from any live thread.

While the absence of a reference graph leading to an object is a clear and easy-to-test proof that an object is unreachable, the presence of such a reference, does not necessarily imply that a “potential continuing computation” will actually access it. This is harder to test, but whether an implementation actually does it doesn’t affect whether the object is formally “eligible to garbage collection”*.

The specification even makes clear:

Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.

We have an unused parameter, args, here, pointing to a string array, eligible to garbage collection. In fact, the array may point to an arbitrary number of strings eligible to garbage collection in this example, which leads again to the conclusion that the number of collectible objects is unknown.

The same applies to the local variable a2. As long as it is not subsequently used, it does not prevent the referent (and in turn the Beta instance referenced by a2.b2) from garbage collection.

See also Can java finalize an object when it is still in scope? regarding this topic and finalize() called on strongly reachable objects in Java 8 regarding real life problems caused by naive assumptions about garbage collection.

Though, these are about observable behavior. In the question’s code, neither Alpha nor Beta have finalize() methods that would make the collection of their instances observable, so in principle, the JVM could reclaim the memory of all objects, including the one referenced by a static field, without anyone noticing.


* One thing, these questions rarely say, is whether they’re talking about theory or practice. Formally, far more objects are eligible for garbage collection than an implementation may actually identify. The ability to identify unused variables may depend on the optimization state and a short main method rarely gets optimized. On the other hand, the garbage collector usually doesn’t even run for such a short execution, but rather, the JVM will release the entire heap en bloc.

So in theory, almost all objects are eligible to garbage collection, whereas in practice, none gets collected at all. So neither view leads to the number, the asker wants to hear…

Holger
  • 285,553
  • 42
  • 434
  • 765
  • excellent answer and to the point. I got a similar interview question recently, did my best to get a - "this is not correct". I smiled and left the room in 5 minutes; exactly your point about "has put a particular gotcha into the question and will consider any answer correct which identifies the gotcha". – Eugene Aug 27 '19 at 13:20