Hi Rob,
Here are my annotations:
12. X3 x2 = new X3();
Line 12 creates a reference variable named x2 of type X3. Then it creates a new object of type X3. (To help keep track of the objects that get created in this code snippet, let's call this new object "ObjectOne".) Finally, it references ObjectOne with the reference variable x2. We'll keep track of reference variables and the objects they refer to with this unofficial shorthand:
x2 --> ObjectOne
13. X3 x3 = new X3();
Line 13 is a lot like line 12. It creates a reference variable named x3 of type X3. Then it creates a new object of type X3. (Let's call this new object "ObjectTwo".) Finally, it references ObjectTwo with the reference variable x3.
x2 --> ObjectOne
x3 --> ObjectTwo
14. X3 x5 = x3;
Line 14 creates a reference variable named x5 of type X3 and gives it the same object reference that x3 has. What's that? Well, up in line 13 x3 was told to refer to ObjectTwo, so that's what x5 gets too.
x2 --> ObjectOne
x3 --> ObjectTwo
x5 --> ObjectTwo
15. x3 = x2;
Now x3, which was told to reference ObjectTwo up in line 13, is told to change its reference to whatever x2 is referencing. That would be ObjectOne, from line 12.
x2 --> ObjectOne
x3 --> ObjectOne
x5 --> ObjectTwo
16. X3 x4 = x3;
A new reference variable named x4 of type X3 is created, and told to reference whatever x3 is referencing.
x2 --> ObjectOne
x3 --> ObjectOne
x5 --> ObjectTwo
x4 --> ObjectOne
17. x2 = null;
Change x2 so it doesn't reference anything. Notice that the only reference variable referring to ObjectTwo is x5, so if x5 is changed, ObjectTwo will have no live references and will thus be eligible for garbage collection.
x2 --> null
x3 --> ObjectOne
x5 --> ObjectTwo
x4 --> ObjectOne
18. // insert code
Q: What two lines of code, inserted independently at line 18, will make an object eligible for garbage collection? (Choose two.)
In other words, we've created two objects. What can we do so that one of them will be left with no live reachable reference variable?
A. x3 = null;
x2 --> null
x3 --> null
x5 --> ObjectTwo
x4 --> ObjectOne
Since x4 is still referencing ObjectOne, this doesn't do it.
B. x4 = null;
x2 --> null
x3 --> ObjectOne
x5 --> ObjectTwo
x4 --> null
Since x3 is still referencing ObjectOne, this doesn't do it.
C. x5 = null;
x2 --> null
x3 --> ObjectOne
x5 --> null
x4 --> ObjectOne
This leaves ObjectTwo without any live references. Eureka!
D. x3 = x4;
x2 --> null
x3 --> ObjectOne
x5 --> ObjectTwo
x4 --> ObjectOne
This doesn't really change anything, since x3 and x4 were already referencing the same object, ObjectOne.
E. x5 = x4;
x2 --> null
x3 --> ObjectOne
x5 --> ObjectOne
x4 --> ObjectOne
This leaves ObjectTwo without any live references, since x5 has been changed to reference ObjectOne. Double eureka!!
Hope that helps.
Tom Cockerline