6

I am preparing for OCPJP, and I got stuck at the following mock exam question:

Given:

3. interface Animal { void makeNoise(); }

4. class Horse implements Animal {
5.     Long weight = 1200L;
6.     public void makeNoise() { System.out.println("whinny"); }
7. }

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

10.    public static void main(String[] args) {
11.        Icelandic i1 = new Icelandic();
12.        Icelandic i2 = new Icelandic();
12.        Icelandic i3 = new Icelandic();
13.        i3 = i1; i1 = i2; i2 = null; i3 = i1;
14.    }
15. }

When line 14 is reached, how many objects are eligible for the garbage collector?

A. 0

B. 1

C. 2

D. 3

E. 4

F. 6

Their correct answer is E, i.e. four objects, but I'm not sure why. From my point of view, i2 and its weight will get eligible for garbage collection. Perhaps I'm missing something, please advise.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user998692
  • 5,172
  • 7
  • 40
  • 63
  • 4
    Their question is a little silly as garbage collection is irrelevant at program termination (at line 14)... – DNA Nov 29 '12 at 21:14
  • Just a clarification - are you sure that `weight` is a `Long` and not a `long` (object, not primitive)? – DNA Nov 29 '12 at 21:16
  • 3
    Wait...doesn't this entirely depend on how this program is called? Strings are objects, so any arguments provided would change the number of objects. – Mike G Nov 29 '12 at 21:17
  • Those `String` are in the string constant pool, so they are not eligible for garbage collection (at least in the sense of the question). – user802421 Nov 29 '12 at 21:38
  • Yes, I'm sure weight is Long, I made copy-paste for the entire code. – user998692 Nov 30 '12 at 13:43

3 Answers3

8

Lets call Icelandic() on line 11 IceA, line 12 IceB, and so forth.

After creation

i1 = IceA
i2 = IceB
i3 = IceC

After i3 = i1

i1 = IceA
i2 = IceB
i3 = IceA

After i1 = i2

i1 = IceB
i2 = IceB
i3 = IceA

After i2 = null

i1 = IceB
i2 = null
i3 = IceA

After i3 = i1

i1 = IceB
i2 = null
i3 = IceB

So only the Icelandic() created on line 12 remains. Now, each Icelandic() has a Long weight, so IceA and IceC are now unreferenced, meaning 4 objects (IceA, IceA.weight, IceC, IceC.weight) are available for GC.


Other issues:

  1. args is still args, they are not counting going out of scope in this question
  2. Long weight is not declared statically, so each instance of the class has a weight object.
Community
  • 1
  • 1
durron597
  • 31,968
  • 17
  • 99
  • 158
3

Let's call the first Icelandic object that is created "A", the second one "B", and the third one "C". After line 12, they are referenced by i1, i2, and i3, respectively.

Now, we do:

i3 = i1; // object "C" is no longer referenced, object "A" is now referenced by i1 and i3
i1 = i2; // object "A" is just referenced by i3, object "B" is referenced by i1 and i2
i2 = null; // object "B" is just referenced by i1 now
i3 = i1; // object "B" is referenced by i1 and i3, object "A" is no longer referenced

So, objects "A" and "C" are no longer referenced, and they along with their "weight" are eligible for garbage collection, so four objects total.

GriffeyDog
  • 8,186
  • 3
  • 22
  • 34
  • But *all* of these references are out of scope, and therefore don't prevent GC of any of these objects – DNA Nov 29 '12 at 21:25
  • 1
    @DNA, I take "when line 14 is reached" to mean just prior to `main()` being exited. Apparently, that's what the writers of the question intended if the answer is 4. – GriffeyDog Nov 29 '12 at 21:28
  • @DNA: I agree with you, but I think the question asker is saying "BEFORE line 14", not "After variables go out of scope" – durron597 Nov 29 '12 at 21:29
  • Ah, that would explain it - it changes the meaning of the question entirely and makes all the messing around on line 13 relevant (otherwise it's a rather cruel diversion in an exam question!) – DNA Nov 29 '12 at 21:31
  • 1
    Right, it would have been better for the question writer to insert an actual line of code (like `System.out.println()` or something similar) at line 14 instead of the closing brace. – GriffeyDog Nov 29 '12 at 21:32
2

You will have 4 objects in the system, 3 Icelandic instances and 1 Long instance.

When you assign constant object to some variable, compiler uses kind of private static final Long long1200 = Long.valueOf(1200L); object that is shared by all weight instances.

Primitive type wrappers are immutable, so it is safe to do this optimization.

EDIT: probably I am wrong, because this would work this way if we referenced the same constant several times here, which is not the case

hoaz
  • 9,883
  • 4
  • 42
  • 53
  • You are semi-correct: The compiler or the Long implementation *is* optimizing the instances for smaller numbers so that it's only one. For larger numbers no longer: http://ideone.com/nsQoHr – zapl Nov 29 '12 at 22:16
  • Sure, this is runtime optimization of `Long.valueOf()`, I thought compiler does constant optimization too, and that appeared to be wrong – hoaz Nov 29 '12 at 22:20