How many objects will be eligible for garbage collection after executing "m1=null; m2=null;"?

JavaGarbage Collection

Java Problem Overview


I am confused to understand after executing m1 = null; m2 = null;. How many objects will be eligible for garbage collection?

public class MyTest {
    MyTest m;

    void show() {
        System.out.println("Hello this is show method.");
    }

    public static void main(String args[]) {
        MyTest m1 = new MyTest();
        MyTest m2 = new MyTest();
        MyTest m3 = new MyTest();
        m1.m = m2;
        m2.m = m3;
        m3.m = m1;
        m1 = null;
        m2 = null;
        // Question here: How many objects will be eligible for garbage collection?
    }
}

Java Solutions


Solution 1 - Java

Zero.

Object reference diagram looks like this:

Circular

You can see that the reference is circular. A reference from main to m3 keeps the m3 object alive. In turn, m3 keeps alive m1, which keeps m2 from GC.

Note that if you set m3 to null, all three objects would become eligible for GC at once, despite circular references existing for each one of them. GC is smart enough to figure out that all references are coming from GC-eligible objects, and collect all three.

Solution 2 - Java

Potentially all 3 of them. No variables are referenced after the // marker, so the optimizer is within its rights to drop them off the frame at this point.

Solution 3 - Java

Voila! GC will collect nothing here! Let's see what actually is going on here. When you created three objects of m1, m2 and m3 of MyTest, the object was created like below (say the object reference id starts from 410):

m1    MyTest  (id=410)
    m    null
m2    MyTest  (id=412)
    m    null
m3    MyTest  (id=414)
    m    null

When you initialize

m1.m = m2;
m2.m = m3;
m3.m = m1;

The objects are now looks like:

m1    MyTest  (id=410)
    m    MyTest  (id=412)
m2    MyTest  (id=412)
    m    MyTest  (id=414)
m3    MyTest  (id=414)
    m    MyTest  (id=410)
        m    MyTest  (id=412)
            m    MyTest  (id=414)
                m    MyTest  (id=410)
                    .
                    .
                    . (This is circular)

But after you reinitialized m1 and m2 to null, the objects look like:

m1    null
m2    null
m3    MyTest  (id=414)
    m    MyTest  (id=410)
        m    MyTest  (id=412)
            m    MyTest  (id=414)
                m    MyTest  (id=410)
                .
                .
                .

Look, m1 and m2 are null now, but their references are still alive in m3!

Solution 4 - Java

None as they are still all reachable through the circular reference you build there through m3

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser5347751View Question on Stackoverflow
Solution 1 - JavaSergey KalinichenkoView Answer on Stackoverflow
Solution 2 - JavaJoshuaView Answer on Stackoverflow
Solution 3 - Javarakeb.mazharulView Answer on Stackoverflow
Solution 4 - JavaAron_dcView Answer on Stackoverflow