Wednesday, May 24, 2023

Quiz yourself: When is a Java object still reachable?

Quiz yourself, Java object, Oracle Java, Oracle Java Certification, Oracle Java Prep, Java Career, Java Guides, Java Learning, Java Object

The garbage collector can’t collect an object until it’s no longer available to any live thread.


Given the following code

interface Repairable {}
class Car implements Repairable {
  class Clutch implements Repairable {}
  private Clutch c;
  public Car() {
    c = new Clutch();
  }
  public Clutch getClutch() {
    return c;
  }
}

and a method fragment

01: var rl = new ArrayList<Repairable>();
02: var car = new Car();
03: var clutch = car.getClutch();
04: var engine = (Repairable) null;
05: rl.add(car);
06: rl.add(clutch);
07: car = null;
08: clutch = null;
09: rl.add(engine);
10: rl.set(2, engine);
11: rl.remove(0);
12: rl.remove(1);

After which line will the Car instance created at line 02 become eligible for garbage collection? Choose one.

A. It will become eligible after line 07.
B. It will become eligible after line 08.
C. It will become eligible after line 10.
D. It will become eligible after line 11.
E. It will become eligible after line 12.
F. It will not become eligible after line 12.

Answer. An object becomes eligible for the garbage collection process when it is no longer reachable. Section 12.6.1 of the Java Language Specification states the following about finalization:

A reachable object is any object that can be accessed in any potential continuing computation from any live thread.

For this question, it’s sufficient to consider only the single thread executing this code and the variables that are declared within it. There are four such variables: rl, car, clutch, and engine. From those variables, you should consider the transitive reachability. That is, if you have added car to the list, you can get at car through the reference rl, because you can follow rl to the list and then from the list you can access car. All such transitive reachability must be considered.

Now, look at the state of these variables at key points in the code.

By the end of line 06, the variable rl refers to the ArrayList, and that list contains references to both the Car and the Clutch objects. At that same point, the car variable also refers to the Car object. Clearly the Car object is reachable at this point.

By the end of line 10, the car and clutch variables have been nulled out—but the list still contains references to both the Car and Clutch objects, so the Car object is still reachable.

At this point, the list’s contents are the car, the clutch, and null. Note that line 09 appends engine (which contains null) to the list, placing null at index 2. Then line 10 sets the value at index 2 to the engine value: null. Line 10, therefore, has no meaningful effect on the state of things.

Line 11 removes the item at index 0, which is the car. At first sight, that might seem to be the last reference to the car, but you’ll see in a moment that it’s not. Continuing to trace the execution, at this point the list now contains the clutch and null.

Line 12 removes the item at index 1, which is the null. The list, therefore, contains nothing except the clutch.

What’s not immediately obvious is that the Clutch object itself, which is an inner class, contains a reference to its enclosing instance, which is the Car object. Because of that reference, the Car object is still reachable after line 12, which makes option F the correct answer and the other options incorrect.

This reference to the enclosing instance is usable by the programmer. If you were to add a toString method, such as the following, to the Clutch the reference, Car.this would provide access to the car to which this clutch belongs. It’s worth noting that in Java, the access control rules are such that the features of a Car object are accessible from the Clutch class even if they are private, and the features of Clutch are likewise accessible to Car—again, even if they are private.

class Clutch implements Repairable {
  @Override
  public String toString() {
    return "Clutch of car " + Car.this;
  }
}

Conclusion. The correct answer is option F.

Source: oracle.com

Related Posts

0 comments:

Post a Comment