0

I got a question really confuses me,

After running Line 8 of the following code, which objects are eligible for garbage collection?

public class X 
{
    public static void main(String [] args) 
    {
        X x = new X();
        X x2 = m1(x);          /* Line 6 */
        X x4 = new X();
        x2 = x4;               /* Line 8 */
        doComplexStuff();
    }
    static X m1(X mx) 
    {
        mx = new X();
        return mx;
    }
}

A.x
B.x and x2
C.x and x4
D.x4

My initial thought was only x2 is garbage collected because it is deferenced at line 8 when x2 = x4, and since java is pass by value, so X x2 = m1(x) won't affect x.

I've also found the exact same question (but different choices) here https://www.indiabix.com/java-programming/garbage-collections/discussion-202, and some comments saying x also should be garbage collected as well, which are contradictory to my thought, now I'm confused which choice to the question is correct, thanks in advance.

VinceFIT
  • 23
  • 2
  • 6
  • 1
    Your understanding is correct. The only object eligible for GC is the one referenced by `x2`. – shmosel Nov 09 '17 at 06:24
  • 2
    Possible duplicate of [Is Java "pass-by-reference" or "pass-by-value"?](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value) – Kaustubh Khare Nov 09 '17 at 06:27
  • *All of them*. Being referenced by a local variable is not sufficient to prevent garbage collection. During the run of `doComplexStuff()`, none of these objects is used and there will be no subsequent use. Whether or not the JVM is actually capable of collecting them, depends on technical details, e.g. whether the JIT/optimizer has already processed the code, but these technical details do not change that *in principle*, all of these objects are allowed to get garbage collected. – Holger Nov 15 '17 at 14:52

3 Answers3

2

As many have answered object referenced by x2 is garbage collected. Here is a sample code that allows you to check the GC for yourself and this code also demonstrates Java's behavior of:

Java manipulates objects by reference,but it passes object references to methods by value.

public class GCInJava 
{
     int i=0;
    String name="default";
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("[GCing object referenced by: "+this.name+"]");
    }
    public static void main(String [] args) 
    {
        GCInJava x = new GCInJava();
        x.name="x";
        System.out.println("x before calling m1(): "+x);
        System.out.println("x.i before calling m1(): "+x.i);
        GCInJava x2 = m1(x);    
        System.out.println("x.i after calling m1(): "+x.i);
        System.out.println("x after calling m1(): "+x);
        System.out.println("x2.i: "+x2.i);
        GCInJava x4 = new GCInJava();
        x4.name="x4";
        x2 = x4;               
        System.gc();
        doComplexStuff();
    }
    static GCInJava m1(GCInJava mx) 
    {
        System.out.println("mx before new object: "+mx);
        mx = new GCInJava();
        mx.i=10;
        mx.name="mx/x2";
        System.out.println("mx after new object: "+mx);
        return mx;
    }
}

Note: System.gc() may not always trigger garbage collection by JVM; So try running the code a few times.

Sample output(notice the hash codes printed):

x before calling m1(): tests.GCInJava@64c3c749
x.i before calling m1(): 0
mx before new object: tests.GCInJava@64c3c749
mx after new object: tests.GCInJava@7150bd4d
x.i after calling m1(): 0
x after calling m1(): tests.GCInJava@64c3c749
x2.i: 10

[GCing object referenced by:mx/x2]

Community
  • 1
  • 1
NAK
  • 478
  • 2
  • 9
1

I don't think this is a particularly well-phrased question.

First of all, variables can't be eligible for garbage collections, objects can. So saying x2 is eligible for GC means nothing, because then I can say that mx is also eligible, since the method returned. This makes it look like as if there are more objects in memory than there actually are.

This is more accurate

The object created at line 12 is eligible for GC.

In addition, the object created at line 5 is not eligible, x is still referencing it. Just try printing out the value in x. You will see that it is not null.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • @piet.t Edited. – Sweeper Nov 09 '17 at 07:39
  • This is a nonsensical test. If you insert the a statement that will print `x`, it’s that inserted statement that prevents the garbage collection of `x`. That doesn’t prove that the object referenced by `x` was not garbage collected when the print statement did not exist. Especially as garbage collectors never set references to `null`. It would be nonsensical to set something to `null` that has just been proven to be *unused*. – Holger Nov 15 '17 at 14:59
0

Yes, you are right.

Java is "pass by value", and only mx, mx = new X();, is garbage collected.

And x is not garbage collected. For example;

public class X
{
    public static void main(String [] args)
    {
        X x = new X();
        X x2 = m1(x);
        X x4 = new X();
        x2 = x4;
        doComplexStuff();
        System.out.print(x); // no problem; line 10
    }
    static X m1(X mx) 
    {
        mx = new X();
        return mx;
    }
}

If x is garbage collected, the line 10 is error. In fact, it is not. So, x is not garbage collected

fxleyu
  • 119
  • 8
  • Hi fxleyu, thanks for your answer, is x2 garbage collected too? if not why? I thought when x2 = x4 at line 8, the original value of x2 is derefenced and goes to garbage collection. – VinceFIT Nov 09 '17 at 07:05
  • Yes, `x2`, you refer, is `mx`, `mx = new X();` ; – fxleyu Nov 09 '17 at 07:27