Below is an example of Composition:
public class A3 {
B b = new B();
}
What I learned is that as soon as object of A3
is GC'ed (or becomes eligible for GC), object of B
will also be GC'ed (or becomes eligible for GC).
Now, let's consider below situation, so as per my understanding after d.m1();
, a3
object on heap will become eligible for GC, but I don't think that b
object becomes eligible for GC.
My two understandings are contracting with each other, could someone please help me identify which one is wrong.
public class Testing {
public static void main(String[] args) {
D d = new D();
d.m1();
d.m2();
// do some more things...
}
}
public class A3 {
B b = new B();
public B getB() {
return b;
}
}
public class B{
public void m1() {
System.out.println("B.m1");
}
}
public class D{
B bd2;
public void m1() {
A3 a3 = new A3();
bd2 = a3.getB();
}
public void m2() {
bd2.m1();
}
}
UPDATE: I do understand difference between "eligible for GC" and "actually getting GC'ed", so for sake of convenience, let's say object will immediately be GC'ed once it becomes eligible.
What @Shadab and @Koenigsberg has said is right, here is some explanation with a demo - basically what I did is I have overridden the finalize()
method so as to show you how objects are getting GC'ed.
d.m1();
is over.test1();
is over. If you comment out test2();
then "D is garbage collected" will not be printed because once stack frame of test1
method was removed, there was no (forced) GC , and as long as stack frame of test1
is present on the stack, object d
anyways cannot be removed.Another important point to note is you can check yourself on which objects can be GC'ed by starting from the root object, in this example object of class Testing
will be your root object, so at each step you can try to see whether you can reach a particular object by starting from your root object or not, any object which is not reachable from your root tree becomes eligible for GC.
public class Testing {
public static void main(String[] args) {
test1();
test2();
}
private static void test1() {
Testing t = new Testing();
D d = t.new D();
d.m1();
System.gc();
d.m2();
System.gc();
// do some more things...
}
private static void test2() {
System.gc();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.gc();
}
}
public class A3 {
B b = new B();
public B getB() {
return b;
}
@Override
protected void finalize() throws Throwable {
System.out.println("A3 is garbage collected");
}
}
public class B {
public void m1() {
System.out.println("B.m1");
}
@Override
protected void finalize() throws Throwable {
System.out.println("B is garbage collected");
}
}
public class D {
B bd2;
public void m1() {
A3 a3 = new A3();
bd2 = a3.getB();
}
public void m2() {
bd2.m1();
}
@Override
protected void finalize() throws Throwable {
System.out.println("D is garbage collected");
}
}