1

Four objects are eligible for garbage collection when i3 = null; is executed in the class shown below. I've added comments to explain how I got this answer. Is my reasoning correct?

public class Icelandic extends Horse{
    public void makeNoise(){
        System.out.println("vinny");
    }

    public static void main(String args[]){
        /**
         * 2 objects created
         */
        Icelandic i1 = new Icelandic();

        /**
         * 2 objects created
         */
        Icelandic i2 = new Icelandic();

        /**
         * 2 objects created
         */
        Icelandic i3 = new Icelandic();

        /**
         * i3 is now pointing at i1, original Icelandic() referred to by i3 now
             * has no reference -  2 objects now have no reference
         */
        i3 = i1;

        /**
         * i3 is now pointing at i1, original Icelandic() referred to by i1 now
             * has no reference -  2 objects now have no reference
         */
        i1 = i2;

        /**
         * Total of six objects created, 4 objects no longer have a reference so 4
             * can be garbage collected.
         * 
         * Setting to null below doesn't make any difference to garbage collector
             * as objects now do not have a reference
         */
        i2 = null;
        i3 = null;
    }
}

interface Animal {
    void makeNoise();
}

class Horse implements Animal{
    Long weight = 1200L;

    public void makeNoise() {
        System.out.println("whinny");
    }    
}
Igor
  • 33,276
  • 14
  • 79
  • 112
blue-sky
  • 51,962
  • 152
  • 427
  • 752
  • 1
    I think it is more appropriate to say that one object was created when creating `Icelandic`. Even though class itself is inherited. –  Nov 25 '11 at 16:36
  • There's a difference between a class and an object. When you inherit from a class and create one object, this will be just one object. – Thomas Jungblut Nov 25 '11 at 16:43
  • If you calculate hierarchy (I suppose it's wrong) you should also include Object, because every class extends it. – mishadoff Nov 25 '11 at 16:45
  • I believe that `Long weight` has to be taken into account as well as it's also an object. `1200L` is too large to take benefit of flyweight pattern (anything between -128 and 127 returns the same cached instance). Maybe it's such a catch-question? – BalusC Nov 25 '11 at 16:47
  • Why do you think 6 objects are created? – kittylyst Nov 25 '11 at 16:50
  • 1
    @kittylyst: I have the impression that it's actually the real answer which says that 4 objects are eligible for GC and the OP just wanted to figure and confirm that. – BalusC Nov 25 '11 at 16:51
  • That's correct Balusc, I should have pointed that out – blue-sky Nov 25 '11 at 17:25

2 Answers2

12

These are steps of your program:

    Icelandic i1 = new Icelandic();
    Icelandic i2 = new Icelandic();
    Icelandic i3 = new Icelandic();

enter image description here

    i3 = i1;
    i1 = i2;

enter image description here

    i2 = null;
    i3 = null;

enter image description here

So the last diagram concludes that only 2 objects are ready for garbage collection. I hope I am clear. You can see object names as references to the objects.

EDIT:

As said by BalusC, Long weight = 1200L is also object. So 2 more objects each for i1 and i3 are eligible or garbage collections. So in all 4 objects are eligible or garbage collection.

prap19
  • 1,818
  • 3
  • 16
  • 26
  • 4
    Excellent presentation. But I think that you've got to take that `Long weight = 1200L` into account as well as it seems that the *actual* answer as stated in the SCJP question is that 4 are eligible for GC. – BalusC Nov 25 '11 at 16:52
  • @BalusC how does Long weight make a difference to garbage collection process? I mean only 1 copy is created for horse, animal and Icelandic in a single object. Can you elaborate on that? – prap19 Nov 25 '11 at 16:56
  • @BalusC is correct, I didn't scroll down all the way when I initially read the question (I only noticed it during editing). Since each Icelandic IS-A Horse, each one gets its own copy of weight as a member. And since it's capital-L `Long`, weight is an object. – Pops Nov 25 '11 at 16:57
  • @LordTorgamus yea that makes sense now, just tried few things. I have edited my answer. Let me know if I am wrong – prap19 Nov 25 '11 at 17:01
  • Indeed. Note that if it were a value between -128 and 127 it would end up being only 1 reference (flyweight!) which is referenced by 3 `IceLandic` objects and in the end not be GC'ed at all but just kept in the flyweight cache of the `Long` class. – BalusC Nov 25 '11 at 17:02
  • Does the flyweight cache have another name, @BalusC? I'm getting nothing from Googling for it. – Pops Nov 25 '11 at 17:12
  • @Lord: http://en.wikipedia.org/wiki/Flyweight_pattern Also check `Long` source code, starting at `valueOf(long)`. All other primitive wrappers have the same construct. That's why `Long#valueOf()` is significantly faster and more memory efficient than `new Long()`. – BalusC Nov 25 '11 at 17:18
  • 1
    Ah, very interesting. Convenience link to `Long` source: http://www.docjar.com/html/api/java/lang/Long.java.html (see lines 572-578) – Pops Nov 25 '11 at 17:35
1

As a very simple rule of thumb, an object in java can be garbage collected if the program's behaviour would not change if all the fields of the object were copied to local variables ( an optimising program transformation ) and all references to the object were set to null.

Quoting 'The Java VM Spec'

12.6.1 Implementing Finalization Every object can be characterized by two attributes: it may be reachable, finalizer-reachable, or unreachable, and it may also be unfinalized, finalizable, or finalized.

A reachable object is any object that can be accessed in any potential continuing computation from any live thread. Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.

Discussion

Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage.

So in your case, as none of the references to any of the Icelandic objects are dereferenced, all of them may be garbage collected immediately . As nothing dereferences i1 to i3, an optimising compiler is at liberty to elide everything after i3 = new Icelandic() as a no-op and collect all six objects immediately.

Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171