Vinayak
Vinayak

Reputation: 13

Why is only 1 object eligible ready for GC?

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.

Upvotes: 1

Views: 103

Answers (1)

Holger
Holger

Reputation: 298233

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…

Upvotes: 3

Related Questions