Discussing the design, decisions and discovery involved in developing Mutability Detector, an open-source analysis tool for Java.

Tuesday, 13 July 2010

EscapedThisReferenceChecker - A Sketch Of A Checker To Come

In a previous entry I discussed some of the rules for immutability, and how they are enforced in Mutability Detector through a set of "checkers". So, for example, where a method can change the reference of an object's field (i.e. a setter method) there is a checker (named SetterMethodChecker) which can detect this rule and render a class definitely not immutable.

This blog entry is aimed at discussing another checker which doesn't exist, but should, before a 1.0 release can be considered.

EscapedThisReferenceChecker

This can be a bit tricky to explain, the first hit for "immutability escape constructor" explains it pretty well. Basically, if you're constructing an object, and someone can get hold of a reference to it before the constructor has completed, there are no guarantees about what that part-constructed object which actually consist of. A code example will help. We'll start with an immutable class, and to keep a theme going I'll call the class IAmImmutable. For those unfamiliar with java.lang.String, it's necessary to know that it is immutable too.


public final class IAmImmutable {
  public final String aField;

  public IAmImmutable(String aField) {
    this.aField = aField;
  }
}


A good example of an immutable class. To show how the reference escapes, we'll show a near identical class, MyThisReferenceEscapes.

public final class MyThisReferenceEscapes {
  public final String aField;

  public MyThisReferenceEscapes(String aField) {
    this.aField = aField;
    ReferencePublishingService.publish(this);
  }
}

In this example, the "this" reference escapes before the constructor is complete, as it is passed to a method in another class. Because of the semantics of the Java memory model, within the publish() method, the reference to the MyThisReferenceEscapes instance could have it's field set, or it might not, there's no guarantees of behaviour. Even if the "this" reference escapes in the last line, after all the fields have been assigned, it doesn't matter, it's still escaped in an incomplete state. Since the ReferencePublishingService could do just about anything with that reference, it could lead to the instance of MyThisReferenceEscapes changing across threads, at different times. With this vulnerability, there is no guarantee that the MyThisReferenceEscapes class is immutable.

I envisage that this kind of checker should be relatively straight forward - once the rules are decided. The "this" can't be passed as a parameter, but only to other classes? Static methods in the same class? Instance methods? It also can't be assigned to fields in another class, but again, how about as a static field in the same class? How about as an instance field?
I'm not entirely sure about these things, so I'll have a think about it, then pap the thought off to my subconscious, and see if it comes up with any bright ideas.

No comments:

Post a comment