Tuesday, 13 July 2010

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.

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.

Monday, 5 July 2010

In an earlier post I introduced the Mutability Detector, and how Josh Bloch's rules were used in its development. One point I mentioned was that Josh's rules are a bit on the strict side. I'm using this blog entry to clarify what I meant by that, and get some of the ol' wheels turning on the question: are immutability and subclassing mutually exclusive?

One of the immutability rules from Effective Java is:

2. Ensure that the class can’t be extended.

I'd like to make the case that yes, while preventing your class being extended is not going harm the immutability status it isn't always necessary. There's also the issue to consider that declaring your class final may have benefits, somewhere, at some point, in the hazy world of the Java memory model.

I'm pretty sure everyone would consider this immutable - an instance of IAmImmutable cannot change after construction. However, it fails one of Josh's rules: the class can be extended. So you could have a situation like:

All is well: ComposedOfImmutables, because it's being built on the solid foundation of immutable instances, is easier to understand, debug, reason about, and almost trivial to use in multithreaded applications. That is, however, until IAmImmutable is subclassed, and the menace that is the immutability-ruining LOLclass is free to pollute the otherwise immutable world around it. An instance of ImInUrClassRuiningUrImmutability, because it extends IAmImmutable, can be passed as a parameter to ComposedOfImmutables, corrupted it with mutability. Like so:

This is the case where it's important that IAmImmutable cannot be extended. It's a consumer thing. The existence of a mutable subclass does not mean IAmImmutable instantly becomes mutable. You can still new them up and pass them around multiple threads with joyful abandon. But... ComposedOfImmutables depends on the instance it receives in the constructor being immutable. The onus of immutability in this case does, and should lie, with ComposedOfImmutables.

You may be asking, what's the problem? IAmImmutable obviously wants to be immutable. It lives to be used immutably (is that a word?), why not just prompt the developer to prevent subclassing?. Well, it becomes an issue for static code checking tools, like Mutability Detector. In the past year I spent my honours year project steeped in the stew of static bug checkers, with their incomplete analysis, unsoundness, and swathes of false positives. My research in that area has convinced me that any static analysis tool has to be very, very careful of reporting errors that get in the users way. If it's not reporting real problems they want to fix, it's wasting their time.

[Edit: looking back after the comments made by Seb Charrot, this conclusion was really misleading. Hopefully this revision makes more sense.]

That's why it's my opinion that Josh's rule is too strict. And it's the reason that Mutability Detector will not emit errors that IAmImmutable is in fact mutable, it will instead emit warnings. Instead of an "omg teh buildz broken!", it says "You know, there's a danger here. Gather round to hear why...". However, Mutability Detector has, and will, tell you that ComposedOfImmutables is definitely not immutable. If guarantees can't be made about the runtime instances passed to a class, the foundations it is built on are too weak to support it, and immutability cannot be claimed.

So while most of the time immutability and subclassing are incompatible, hopefully this post has demonstrated that they are not always mutually exclusive.

Sunday, 4 July 2010

(n still to be decided)Mutability Detector is a tool which analyses Java code, and tells you if instances of a given class are immutable or mutable. Having been a google code project for around six months, some recent discussions (one on the issues page, and another in the mailing list for Project Lombok, in an unrelated discussion) have brought a little bit of attention to the project. I thought it would be useful to give an overview of the usage of Mutability Detector, and how it can be used to recognise mutability in your classes.

Mutability Detector works by applying a set of checkers to each class. Each checker looks for a particular way of rendering a class as mutable, and the results from each checker are combined to give the overall "mutability result" of the class. The checkers closely relate to a set of rules for achieving immutability. These began as the rules defined by Josh Bloch in the excellent Effective Java, 2nd Edition. Josh lists five rules (in Item 15), these are:

1. Don’t provide any methods that modify the object’s state (known as mutators).2. Ensure that the class can’t be extended.3. Make all fields final.4. Make all fields private.5. Ensure exclusive access to any mutable components.

These formed a good basis for an everyday tool for ensuring your classes are immutable. But I found them to be a bit on the strict side (more on that in a later blog entry). When first writing the tool, those rules were combined with the following:

1. It should not be possible to reassign any field. (this is almost implicit in Josh's rules 1, 3 & 4)2. An immutable object should consist of immutable fields.This implies three sub-rules. If a field is not constructed directly (i.e. passed as a parameter, or as the result of a method call):i. It must not be possible to subclass the type.ii. It should be declared as a concrete type.iii. If the previous two cannot be achieved, make a copy of in the constructor and assign that to the field.

Some of these rules are pretty opaque for understanding what the tool actually detects (and in the past few days, I've found them to be a bit lacking). What might help understand Mutability Detector is some of the patterns of code which are detected and reported. Listed here is each checker, some example code and the results of applying the checker to that code.

FinalClassChecker

public class MutableByNotBeingFinalClass {

}

MutableByNotBeingFinalClass is MAYBE immutable Is not declared final, and thus may be immutable.

MutableByAssigningAbstractTypeToField is DEFINITELY_NOT immutableField [nameContainer] can have an abstract type (AbstractStringContainer) assigned to it.

(Here the problem is, that while AbstractStringContainer is immutable, StringContainer is not, and either could be passed as a parameter to the constructor. Thus we can never be sure that the field we're assigning to references an immutable object or not. Though this could be relaxed to render types like these as MAYBE immutable.)

InherentTypeMutabilityChecker

This checker is used more to help decide the immutability status for client classes. For example, if a class has a field which is inherently mutable, this affects the containing class.

MutableByHavingArrayTypeAsField is DEFINITELY_NOT immutable Field [names] is a primitive array.

This currently quite limiting - the field 'names' may not actually be mutated, yet the containing class would be declared as mutable. This is definitely something to work on.

Some of these rules aren't complete. Sometimes they don't interact too well with certain classes (inheritance is hairy issue). Common patterns, such as lazily loaded fields, aren't handled at all (thus java.lang.String is supposedly mutable). So there's a lot to do, but hopefully this entry has provided a decent introduction to Mutability Detector.