3

Given:

interface Animal { void makeNoise(); }
class Horse implements Animal {
    Long weight = 1200L;
    public void makeNoise() { System.out.println("whinny"); }
}
public class Icelandic extends Horse {
    public void makeNoise() { System.out.println("vinny"); }
    public static void main(String[] args) {
        Icelandic i1 = new Icelandic();
        Icelandic i2 = new Icelandic();
        Icelandic i3 = new Icelandic();
        i3 = i1; i1 = i2; i2 = null; i3 = i1;  //<-- line 14
     }
 }

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

answer is E. why?

Kevin DiTraglia
  • 25,746
  • 19
  • 92
  • 138

5 Answers5

4

The question, and especially insisting on that particular “correct” answer of 4, doesn’t make much sense, as it draws several assumptions about how a JVM works which are naïve in the best case or simply wrong.

The first thing it does wrong is to assume to know, how many objects are ever created.

The main method creates three instances of Icelandic having an inherited field weight initialized with the value of 1200L. The value 1200L is converted to a Long instance via auto-boxing using the method Long.valueOf which is allowed, but not required to cache frequently requested values. So we can’t predict the number of Long instances created here, it might be one or three, but even two is possible if the caching did not work for all invocations, for whatever reasons.

Then the code is playing around with the local variables holding the three instances and is supposed to hold only one of these instances “after” line 14 but there is no associated code after that line for which this state could have a relevance. The only thing which happens after that line is returning from the main method so after line 14 all local variables are out-of-scope.

Whether there is a point of execution which can be associated with “after line 14” but still being in method main where exactly one instance of Icelandic is in scope depends on whether line debug information have been included in the class file and how the compiler did map byte code instructions to these line numbers.

If the return byte code instruction inserted by the compiler is not associated with line 15, all instances created in the main method might be garbage collected after line 14 but keep in mind that the Long instance might still be referenced from a global cache and hence not be eligible to garbage collection. We simply can’t predict.

There is another aspect of JVM execution: optimization. JVMs are allowed to perform “escape analysis” and elide object creations if they don’t have any impact on the programs semantics. In your program, all objects are unused from a JVMs point of view. So another legal execution scenario is that this main method never creates any object and then there are no object eligible for garbage collection at all.

Holger
  • 285,553
  • 42
  • 434
  • 765
2

So each object holds a Long object, so when each Icelandic object is marked for garbage collection, so is the Long value it pointed to. Therefore after:

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

the original i3 object is lost, and the original i1 value is lost. i1 and i3 both point to the original i2 keeping it alive (and i2 points to null, keeping nothing alive). This leaves 2 objects getting marked for garbage collection (the original i1 and original i3) as well as the Long value they pointed to, giving you 4 items marked for garbage collection.

Kevin DiTraglia
  • 25,746
  • 19
  • 92
  • 138
  • 2
    +1. However, playing devil's advocate, I think the correct answer would actually be "Either 3 or 4, depending on implementation". Although the JLS states primitive values between -128 and 127 must always be interned and thus the same object, it also states "Ideally, boxing a given primitive value p, would always yield an identical reference." So a given compliant JVM implementation could easily cause those `Long` values to be the same object, and in this case only three actual objects would be eligible for collection! – Michael Berry Oct 08 '14 at 18:03
  • @berry120 Wouldn't it be 2 or 4? If all three Long objects are referencing the same object, only the two `Icelandic` objects would get GCd, since both of their `weights` are pointing to the same `Long` reference that the living `Icelandic` is still using. – azurefrog Oct 08 '14 at 18:50
  • 1
    I agree it's not a good question, but given that OP gave the correct answer, I believe this is the reasoning to go along with it. – Kevin DiTraglia Oct 08 '14 at 19:00
  • @KevinDiTraglia Oh sure, I was just pointing it out as an addendum really! – Michael Berry Oct 08 '14 at 21:31
2

enter image description here

I would go with Icelandic 2 objects eligible (object 1 and 3). Since each Icelandic holds a Long object, it gives us 4.

Bruno Franco
  • 2,028
  • 11
  • 20
1

The important stuff is here

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

So i3 loses its reference right away so the original object is ready for collection.

i1 and i3 reference i2 so i1s original object is ready for collection.

Then i2 loses its reference so all 3 are null and garbage collected.

I'd personally go with 3. That's a pretty thought provoking question.

RyPope
  • 2,645
  • 27
  • 51
1

After Line14, Only original i2 Object is alive, no referemce is point to original i1 and i3, so they are eligible for the garbage collector, and this object has a base type, a long field, lose it to, so 2*2 = 4;

LiangQ
  • 26
  • 2