Number of objects to collect garbage
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 suitable for the garbage collector?
and. 0 B. 1 C. 2 D. 3 E. 4 F. 6
Answer: E. Why?
source to share
The question, and especially insisting on this particular "correct" answer 4, doesn't make much sense as it makes several assumptions about how the JVM works that are naive at best or just plain wrong.
The first thing it does wrong is to assume how many objects have ever been created.
The method main
creates three instances Icelandic
that have an inherited weight
value-initialized field 1200L
. The value is 1200L
converted to an instance Long
through automatic boxing using a method Long.valueOf
that is permitted but not required for a cache of frequently requested values. Therefore, we cannot predict the number of instances created here Long
, it can be one or three, but even two are possible if caching does not work for all calls for some reason.
The code is then played back with local variables containing three instances, and should only hold one of those instances "after" line 14, but there is no associated code after that line for which this state might be relevant. The only thing that happens is after this line is returned from the method main
, so after line 14 all local variables go out of scope.
Whether there is an execution point that may be associated with "after line 14" but is still in a method main
where exactly one instance Icelandic
is in scope depends on whether the line debug information is included in and how the compiler did the byte code instruction matching with these line numbers.
If the bytecode instruction return
inserted by the compiler is not linked to line 15, all instances created in the method main
may be garbage collected after line 14, but be aware that the instance will Long
reference the global cache and therefore not be eligible to be collected garbage. We simply cannot predict.
There is another aspect of JVM execution: optimization. The JVM is allowed to perform "escape analysis" and creation of elite objects as long as they do not affect the semantics of the programs. In your program, all objects are not used from the JVM point of view. So another forensic scenario is that this method main
never creates any object and then there is no object suitable for garbage collection at all.
source to share
This way, every object has a Long object, so when every Icelandic object is marked for garbage collection, the value Long
it points to is also indicated. So after:
Icelandic i1 = new Icelandic();
Icelandic i2 = new Icelandic();
Icelandic i3 = new Icelandic();
i3 = i1; i1 = i2; i2 = null; i3 = i1;
the original i3 is lost and the original i1 is lost. i1 and i3 point to the original i2 backing it (and i2 points to zero, keeping nothing alive). This leaves 2 objects marked for garbage collection (original i1 and original i3) as well as the value Long
they pointed to, which gives you 4 items marked for garbage collection.
source to share
Important stuff here
Icelandic i1 = new Icelandic();
Icelandic i2 = new Icelandic();
Icelandic i3 = new Icelandic();
i3 = i1; i1 = i2; i2 = null; i3 = i1;
So, it i3
loses its link immediately, so the original object is ready to be collected.
i1
and a i3
link i2
, so the original i1s object is ready to be collected.
Then it i2
loses its reference, so all 3 have zero and garbage collection.
I will personally go with 3. This is a pretty thoughtful question.
source to share