4
votes
class Beta { }

class Alpha {
static Beta b1  ;
Beta b2;
}

public class Tester {

public static void main(String[] args) {

    Beta b1 = new Beta();
    Beta b2 = new Beta();
    Alpha a1 = new Alpha();
    Alpha a2 = new Alpha();

    a1.b1 = b1 ;
    a1.b2 = b1 ;
    a2.b2 = b2 ;

    a1 = null ;
    b1 = null;
    b2 = null;

    System.out.println(" Line 1    " + " a1   "  + a1.b1);
    System.out.println(" Line 2    " + " a1   "  + a1.b2);
    System.out.println(" Line 3    " + " a2   " + a2.b2);
    System.out.println(" Line 4    " + " a1   " + a2.b1);
    System.out.println(" Line 5    " + " b1   " + b1);
    System.out.println(" Line 6    " + " b1   " + b2);

  }

 }  

I am not sure why only a1 object is available for garbage collection in the above program. I am expecting a1 , b1 and b2 to be collected by garbage collector.

As you can see a1 , b1 and b2 were made NULL hence this is making objects to be available for garbage collection. If object is NULL or unreachable by any thread or reference variable it should be collected by garbage collector.

Can someone help me understand the subtleness of the above program with good example and in more precise way ? Your help is appreciated.

5
You can't "make an object null" in Java. You can null out a reference to the object, though. In any event, you can't really "observe" garbage collection in Java unless you use weak references or the like.Louis Wasserman
how did you find out that b1 and b2 are not garbage collected?Byter

5 Answers

7
votes

Because there is still reference exists to objects pointed by b1 & b2 refrences due to below lines.

a1.b1 = b1 ;
a1.b2 = b1 ;
a2.b2 = b2 ;

Assume like this:

  b1--->BetaObj1
    b2---BetaObj2
    a1---> AlphaObj1
    a2---> AlphaObj2

a1.b1 points to b1 that means, there is reference to BetaObj1 a1.b2 points to b1 that means, there is another reference to BetaObj1

(At this point there are 3 references to BetaObj1)

a2.b2 points to b2 that means, there is reference to BetaOBj2

(At this point there are 2 references to BetaObj2)

a1=null; makes AlphaObj1 eligible for GC

b1=null; makes BetaObj1 reference count to 2, so this object is not eligible for GC

b2=null; makes BetaObj2 reference count to 1, so this object is not eligible for GC.

1
votes
  • b2 is not available for gc because there is still a reference a2.b2 to it
  • b1 is not available for gc because Alpha.b1 holds a reference to it (Alpha.b1 is static, don't be confused because it's set using a1.b1)
1
votes

You ought to get a NullPointerException here:

System.out.println(" Line 1    " + " a1   "  + a1.b1);
System.out.println(" Line 2    " + " a1   "  + a1.b2);

At that point, a1 was already set to null, so accessing its member b2 can't work since it doesn't refer to an object anymore. (Accessing the static b1 works since that only requires the class, not an instance.)

As you can see a1 , b1 and b2 were made NULL hence this is making objects to be available for garbage collection.

No, you set some references to these objects to null, while other references to those objects exist, as is the case for b1 and b2, these objects cannot be collected yet.

1
votes

There are several misconceptions here

  • The GC only runs when it needs to. To perform a GC more often than needed would be doing work it doesn't need to.
  • a1.b1 is actually Alpha.b1 as the instance is not important and can even be null using al.b1 is plain confusing.
  • a1.b2 should throw a NullPointerException as a1 is null.
  • Alpha.b1 is set but not cleared anywhere so the object it referenced is not eligible for cleanup. The other objects could be cleaned up but without calling System.gc(); explicitly, its is highly unlikely it need to be run at the point you might expect.
  • a1 is cleared but a2 is not so it won't be cleaned up (until the method returns)
0
votes

Garbage Collection Example

public class GarbageCollection {

    public static void main(String s[]) throws Exception  {
          Runtime rs =  Runtime.getRuntime();
          System.out.println("Free memory in JVM before Garbage Collection = "+rs.freeMemory());
          rs.gc();
          System.out.println("Free memory in JVM after Garbage Collection = "+rs.freeMemory());
       }
}

Program Output:

Free memory in JVM before Garbage Collection = 62767488

Free memory in JVM after Garbage Collection = 62854120