2

this question is like my previous one 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();
13.    Icelandic i3 = new Icelandic();
14.    i3 = i1; i1 = i2; i2 = null; i3 = i1;
15.  }
16. }

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

I chose A but the right answer is E, but I don't know Why?

Community
  • 1
  • 1
Eslam Hamdy
  • 7,126
  • 27
  • 105
  • 165
  • I don't see how it could be `E`, since you're only creating three object instances (ignoring any objects that might be created inside of the `Icelandic` constructor). Unless they're saying `args` is also a candidate for garbage collection on the grounds that `main()` is about to return and terminate the program. – aroth Sep 02 '12 at 09:29
  • @vainolo it's in between 13 and 15. :-) – peeyush Sep 02 '12 at 09:31
  • 1
    Notice the `weight` field. Its type is `Long` so it's an object as well. Two instances of `Icelandic` are garbage collected and so are their weights. – toniedzwiedz Sep 02 '12 at 09:31
  • 1
    if "when line 14 is reached" means line 14 is not executed, then 0. if it means otherwise, then 4. – gigadot Sep 02 '12 at 09:38
  • @Tom - Fair enough, but isn't that essentially double counting? I think by pointing out that an instance of `Icelandic` will be garbage collected, it's implied that all of that instance's fields will be collected as well. Though the author of the question seems to disagree. – aroth Sep 02 '12 at 09:45
  • It's a tricky exam. It actually gets even more complicated because the garbage collection of these fields actually depends on the `Long` values in question. Like Tomasz Nurkiewicz said in his answer, if they're small enough to fit in the `LongCache`, they are reused. Look at line *546* in [the source of java.lang.Long](http://www.docjar.com/html/api/java/lang/Long.java.html). You can also read [this](https://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching) for an explanation. – toniedzwiedz Sep 02 '12 at 09:56
  • looks like a duplicate of http://stackoverflow.com/questions/8271895/garbage-collection-mock-for-the-ocpjp-exam with little modifications – Saideep Annadatha Jul 20 '13 at 16:59

2 Answers2

8

Let's call the three Icelandic objects created in main as A, B and C.

Initialy

  • i1=A, i2=B and i3=C;

After i3 = i1

  • i1=A, i2=B and i3=A;

After i1 = i2

  • i1=B, i2=B and i3=A;

After i2 = null:

  • i1=B, i2=null and i3=A;

After i3 = i1

  • i1=B, i2=null and i3=B

In line 14, there are standing references to only B object of type Icelandic. A and C are lost in the running program.

Each Icelandic object that is lost gives garbage collector two objects to collect, ie. the Icelandic object itself and the Long object within every Icelandic, which make the total number of garbage collected objects 4.

Since makeNoise methods are never called, they do not change the outcome.

Tugrul Ates
  • 9,451
  • 2
  • 33
  • 59
  • Would it make any difference if `makeNoise()` methods **were** called? – Tomasz Nurkiewicz Sep 02 '12 at 09:50
  • 2
    @Tomasz Nurkiewicz: It depends on the implementation of `System.out.println`. – Tugrul Ates Sep 02 '12 at 09:53
  • i think that i'm missing a rule, i thought that when this assignment executed i1 = i2, i1 will refer to both A & B, but that seems to be wrong, is it true that when that ass. executed i1 won't longer refers to A and refers only to B?? – Eslam Hamdy Sep 02 '12 at 10:08
  • @Eslam: Yes, that's correct. A reference will always point to one and only one object. When you say `i1=x`; `i1` will no longer point to whatever it was pointing before the assignment, it will point to the object that is also pointed by `x`. – Tugrul Ates Sep 02 '12 at 10:11
  • 1
    @junjanes: you are right, `System.out.println()` is free to create as many objects as it wants, +1. – Tomasz Nurkiewicz Sep 02 '12 at 10:23
2

If you look closely, after all assignments in the end i1 and i3 point to the second object while i2 points to null. This means two Icelandic objects are eligible for GC.

Each Icelandic object contains one Long which makes 4 objects eligible for GC in total. Interestingly if the constant was 12L, the answer would be: 2 due to Long internal constant cache. Also note that "whinny" and "vinny" are from the constant pool and won't be garbage collected.

Once you leave the scope where all i1, i2 and i3 are declared, remaining two objects are eligible for GC as well.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674