3
votes

I was asked a question (on this site http://scjptest.com/): How many objects are eligible for garbage collection in this code sample at the line // some code goes here?

class A {
    private B b;
    public A() {
        this.b = new B(this);
    }
}

class B {
    private A a;
    public B(A a) {
        this.a = a;
    }
}

public class Test { 
    public static void main(String args[]) {
        A aa = new A();
        aa = null;
        // some code goes here
    }
}

The correct answer is: "The objects referenced by a and b are eligible for garbage collection.". But why? they contain loop references to each other, they are accessible to each other.

Thank you!

4

4 Answers

5
votes

they contain loop references to each other, they are accessible to each other.

Yes, but they aren't anymore accessible from anywhere else, so they can't be seen and used in the program anymore.

Early GCs had problems collecting such self-referencing object groups but with modern generational collectors it is a solved problem.

In brief, the GC can walk through the web of references from the known static and stack objects, and either

  • copy all objects found to a new memory pool, automatically leaving behind any "dead" objects (this is the "young generation" strategy), or
  • mark all objects found, so that once the whole web of references is walked traversed, it can delete all unmarked objects (this is the "old/tenured generation" strategy).
2
votes

That's because java has a generational garbage collector so it can collect groups of objects that have references between them, but not from the main application.

There is a more in depth explanation here.

As far as I remember (and I might be wrong) this wasn't the case with old versions of java (such as java 1.2), in which the cyclic dependencies had to be cleared manually in order for the GC to collect them.

2
votes

The GC can remove so called "island of objects" if none of the objects from that "island" (or group) cannot be accessed from any thread !

In your example you create an object A that has link to another object B. But the object B is not "reference-able" by anyone expect A. You can view the two objects as an island. When A is gone, GC will be smart enough to figure out that B cannot be referenced by any other thread and thus you will have 2 objects being removed.

1
votes

let's draw the scenario to understand clearly.

A a = new A() 

a ------------this points to object------------> A() "1st object"

in A()'s constructor you instantiate an instance of B() "2nd object"

inside the class B instance is just pointing to the A() above, so no new object created. At the point you assigned a null value to "a" variable, no reference will be pointing to A() object. Now you have 2 objects eligible for GC. Don't worry about the class referencing each other, just focus on the declaration inside your main method.