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

Sunday, 27 January 2013

v0.9 released, java.lang.String now considered immutable!

In the past hour I just released a new version of Mutability Detector, v0.9. This release is quite significant. If you currently use Mutability Detector, I'd highly recommend upgrading. If you've never used it before, there's never been a better time to try*.

* I reserve the right to make this statement on all future releases ;-)

If I've already convinced you, here's the snippet you'll need for your pom.xml:


If I haven't convinced you yet, here's some of the new features that might get you there:

  • you can now use java.lang.String in your immutable classes, without your test failing
  • analysis recognises safe usage of Collections.unmodifiableXXX methods
  • new out-of-the-box "allowed reasons" to help you suppress false positives, in a readable and safe way
  • using the Effective Java-style builder pattern to create immutable objects should now not fail tests
  • we migrated from Google Code to GitHub, so we're in with the cool kids now, right?
  • the usual host of bug fixes and improvements

The String Problem

Finding java.lang.String to be mutable has long been a problem for Mutability Detector, recently rearing it's ugly head during a case study of ThreeTen, the new Date&Time API for Java 8. Although the general case of benign data races has still not been solved, I have taken the pragmatic choice to hard code it as immutable. Similarly for other JDK types, such as the primitive wrappers (Integer, Double, Character, etc), BigDecimal, BigInteger, and Class.

The way String et al have been hardcoded has been exposed to users, so that if you have false positives "tainting" your codebase, you too can tell Mutability Detector to regard certain types as immutable. For further information on this configuration, refer to the JavaDoc.

Unmodifiable Collections

Classes that follow this pattern:

public final class HasUnmodifiableCollection {
    private final List<String>myStrings;
    public HasUnmodifiableCollection(List<String> original) {
        this.myStrings = Collections.unmodifiableList(new ArrayList<String>(original));
    // ...

... are now considered immutable. Provided you use the methods from the standard JDK to copy (the new ArrayList call) and wrap in an unmodifiable collection (the unmodifiableList call) an error won't be raised. That condition is rather strict, for example, I personally use Guava's Lists.newArrayList method to copy, and that is still flagged as an issue. Let me know how useful it is for you.

Those two additions should hopefully make a major difference in the usability of Mutability Detector. Feedback, as always, is welcome.

What's Next?

That kinda depends on the feedback I get, bug fixes that are getting in your way will likely be top priority. More ambitious plans include: allowing mutable fields, provided they are not mutated and don't escape; studying popular projects like Guava to do more case studies, and/or bundle more useful configuration.

Once the release hits Maven Central, I'll also push out a new version of the FindBugs plugin.

Let me know what you'd like to see being worked on!