Immutability in Java

Recently in ##java, we had a discussion on what constitutes “immutability” and how to implement it in java properly. Immutability is a core concept for functional programming, and as mainstream languages and ecosystems “catch up” with the safer, less error-prone ideas from functional programming, immutability is wanted in Java projects as well.

What is immutability?

Asking programmers for their definition of immutability, you will usually receive an answer such as this:

An object is immutable if its state never changes.

In this article we will look at different interpretations of that statement and see how to implement it in java.

Unmodifiable vs. Immutable

An unmodifiable object is an object that cannot be mutated. This does not mean it cannot change through other means:

List<String> inner = new ArrayList<>();
inner.add("foo");
List<String> unmodifiable = Collections.unmodifiableList(inner);
System.out.println(unmodifiable); // [foo]
inner.add("bar");
System.out.println(unmodifiable); // [foo, bar]

Unmodifiable objects are generally not considered “truly” immutable. An immutable version of the code above (using Guava‘s ImmutableList) would be:

List<String> inner = new ArrayList<>();
inner.add("foo");
List<String> immutable = ImmutableList.copyOf(inner);
System.out.println(immutable); // [foo]
inner.add("bar");
System.out.println(immutable); // [foo]

Polymorphism

Designing an immutable class to be extended is tricky business. The base class must either relax its immutability or make basically all of its methods final which makes polymorphism basically useless. Relaxing immutability guarantees will often lead to only an unmodifiable class:

public class Vec2 {
    private final int x;
    private final int y;
    public Vec2(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int getX() { return x; }
    public int getY() { return y; }
    @Override public int hashCode() { return getX() * 31 + getY(); }
    @Override public boolean equals(Object o) { ... }
}

This class appears immutable at first glance, but is it really?

public class MutableVec2 extends Vec2 {
    // redundant fields because super fields are private and final
    private int x;
    private int y;
    public MutableVec2(int x, int y) {
        super(x, y);
        this.x = x;
        this.y = y;
    }
    @Override public int getX() { return x; }
    @Override public int getY() { return y; }
    public void setX(int x) { this.x = x; }
    public void setY(int y) { this.y = y; }
}

We’ve suddenly introduced mutability, and not just that, we also override the two getters, so users of the original “immutable” Vec2 class cannot rely on instances of Vec2 never changing state when using them. This makes Vec2 effectively unmodifiable only, not immutable. Immutable classes should be final.
Limited polymorphism is possible when necessary, for example through a package-private constructor so immutability can be strictly controlled. This is error-prone and should be reserved for exceptional cases.

Defensive copies

Immutability itself does not require immutability on class members (in most definitions). However, in many cases where immutability is used, making sure that members also stay unmodified is desired. This can be done through “defensive copies”:

public class ImmutableClass {
    private final List<String> list;
    public ImmutableClass(List<String> list) {
        this.list = Collections.unmodifiableList(new ArrayList<>(list));
        // when using guava:
        //this.list = ImmutableList.copyOf(list);
    }
    // getter, equals, hashCode
}

Internal state

Internal mutable state is allowed in immutable classes. One use case of this is caching. In OpenJDKs java.lang.String class, which is immutable, the hashCode is cached using this method:

public class String {
    ...
    private int hash; // defaults to 0. not explicitly initialized to avoid race condition (see section below)
    @Override
    public int hashCode() {
        int h = hash;
        if (h == 0) {
            hash = h = computeHashCode();
        }
        return h;
    }
}

(This isn’t the actual implementation but it’s the same principle. Want to see this as implemented in an actual Java runtime library? Here it is.)
To users of this class, the internal state is never visible – they do not see a change in behavior. Because of this, the class still counts as immutable.

Concurrency

Java concurrency is a fickle beast, and immutability is an important tool to avoid the shared mutable state that makes concurrency so difficult. However, immutability has to be implemented carefully to work reliably in concurrent applications.
On top of the basic “state never changes” requirement we must introduce two more requirements: (from Java Concurrency In Practice. Read it, it’s a great book.)

  • All fields must be final.
  • The this reference must never escape the constructor. This is called “proper construction”.

To explore why these requirements are necessary, we will take an example straight from the Java Language Specification:

final class MaybeImmutable {
    private int x;
    public MaybeImmutable(int x) {
        this.x = x;
    }
    public int getX() { return x; }
    // the two threads
    static MaybeImmutable sharedField; // this field isn't volatile
    static void thread1() {
        sharedField = new MaybeImmutable(5);
    }
    static void thread2() {
        MaybeImmutable tmp = sharedField;
        if (tmp != null) {
            System.out.println(tmp.getX()); // could be 5... but could also be 0!
        }
    }
}

At first glance the MaybeImmutable class appears immutable – it does not provide any API to modify its state. The problem with this class is that the field x is not final. Let’s take a look at what both threads do:

// thread1
tmp = allocate MaybeImmutable
tmp.x = 5
write sharedField = tmp
// thread2
read tmp = sharedField
check tmp != null
print tmp.x

In this case, the constructor call is “just” setting the field. If you’re already familiar with the java memory model, you will notice that there is no happens-before ordering between those two threads! This makes the following execution order legal:

// thread1
tmp = allocate MaybeImmutable
write sharedField = tmp
tmp.x = 5
// thread2
// same as above

In that case, thread2 could legally print out “0”.
(Reordering is only one reason why this could happen – caches are another, for example.)
This fact makes our MaybeImmutable class not immutable: From thread2, the state of the same exact instance of MaybeImmutable can change over time. How can we fix this? By making the field x final. Looking at the JLS, this guarantees that when we can see the MyImmutable instance in the sharedField, we can also see the correctly initialized x field. thread2 will always print out 5, as we’d expect.
This visibility guarantee is only given if our class does not leak its this reference before construction is complete, which brings us to our second requirement (“proper construction”):

final class NotImmutable {
    public static NotImmutable instance;
    private final int x;
    public NotImmutable(int x) {
        this.x = x;
        instance = this;
    }
    public int getX() { return x; }
    static void thread1() {
        new NotImmutable(5);
    }
    static void thread2() {
        NotImmutable tmp = instance;
        if (tmp != null) {
            System.out.println(tmp.getX()); // could still be 0!
        }
    }
}

Even though the x field is final in this case, thread2 can see an instance of NotImmutable before its constructor completes, meaning it can still see 0 as the value of x.
Interestingly, setting the x field to volatile in doesn’t help in either example (NotImmutable or MaybeImmutable). The guarantees of final fields are actually different than those of volatile fields here. This is covered in Aleksey Shipilëv’s article “Close Encounters of The Java Memory Model Kind.” This article, together with “Java Memory Model Pragmatics,” is a great resource to learn more about the Java memory model.

Builders

Immutable classes, especially those with many fields, can be difficult to construct – the Java language lacks named parameters. This can be made somewhat easier through the builder pattern, which the following example demonstrates (though only with a single field):

public class ImmutableClass {
    private final String url;
    private ImmutableClass(String url) {
        this.url = url;
    }
    public String getX() {
        return url;
    }
    public static class Builder {
        private String url;
        public Builder url(String url) {
            this.url = url;
            return this;
        }
        public ImmutableClass build() {
            return new ImmutableClass(url);
        }
    }
}
ImmutableClass myInstance = new ImmutableClass.Builder().url("https://yawk.at/").build();

This pattern provides an easy way of constructing very large immutable classes – builders are infinitely more readable than constructor calls such as new ImmutableClass("GET", 6, true, true, false, 5, null). Most IDEs also include utilities to quickly generate such builders.

Lombok

The wonderful project lombok provides a very easy way of writing immutable classes in a few lines of code via the @Value annotation:

@Value
public class ImmutableClass {
    private final String url;
}

This makes the fields private final (if they aren’t already), generates getters and a constructor, and makes the class final. As an added bonus it also generates an equals and hashCode for you. On top of that, you can use the @Builder annotation to also let it generate a builder for you, and the experimental @Wither annotation to generate copy mutators.
To see what kind of code Lombok can generate you can either view the examples on their website or use my javap pastebin to see decompiled lombok-generated code (make sure to select “Procyon” on the bottom-right).

Serialization

Immutable classes do not follow the traditional Java bean layout: They do not have a zero-argument constructor and they do not have setters. This makes serialization using reflection difficult. There are solutions, though – an immutable class constructor can be annotated with serialization-framework-specific annotations to give the framework information on which parameter corresponds to which object property.
We will look at the jackson-databind annotations first:

public final class Vec2 {
    private final int x;
    private final int y;
    @JsonCreator
    public Vec2(@JsonProperty("x") int x, @JsonProperty("y") int y) {
        this.x = x;
        this.y = y;
    }
    public int getX() { return x; }
    public int getY() { return y; }
}

A more framework-agnostic solution exists using the java.beans.ConstructorProperties annotation (not present in android) which is supported by Jackson since version 2.7.0:

public final class Vec2 {
    private final int x;
    private final int y;
    @ConstructorProperties({ "x", "y" })
    public Vec2(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int getX() { return x; }
    public int getY() { return y; }
}

This annotation is also generated on Lombok constructors by default making serializing Lombok-generated immutable classes hassle-free with jackson 2.7+.
Gson takes another approach to deserialization of objects without a zero-argument constructor: sun.misc.Unsafe provides a method to allocate an instance of a class without calling its constructor. Gson then proceeds to reflectively set fields of the immutable object. However, Unsafe is unsupported API and the OpenJDK project is attempting to phase out the class and may remove it entirely in a future JDK version, so this solution should be avoided.
Immutability in Java is not as simple in Java as it might appear at first but with the right tools and patterns, it can be very beneficial to your code base, making your application easier to read, debug and extend and making parallelism much simpler. Be careful of accidentally adding mutability and make use of tools like Lombok to reduce boilerplate associated with immutable classes in Java.

Interesting Links, 2017-Feb-23

Interesting Links – 14-Feb-2017

  • From DZone: Distributed Systems Done Right: Embracing the Actor Model is a reference to a webinar (ugh, “webinar”) from Lightbend on, well, the Actor Model, a way of representing distributed services. Powerful model, even if you don’t use Actors as described.
  • TwelveMonkeys is a set of additional plug-ins and extensions for Java’s ImageIO. It includes BMP, TIFF, JPEG, PNM, and a few others.
  • From user u1dzer0: Awesome Asciidoctor: Include Partial Parts from Code Samples describes how AsciiDoctor can extract, well, partial code samples from a block of code. Given Java’s verbosity (not a bad thing, but a still thing that many people don’t like), having a way to ignore code can help focus on relevance. (Also see: Dexy.)
  • JSON is the new Data Transfer Object is a short reference to JSON – Javascript Object Notation – in Java EE. JSON is becoming one of the more popular serialization formats (and I use “becoming” sarcastically – it’s very popular already). For better or for worse, it’s time. This isn’t a long article, nor is it very deep – but it touches on something that’s become more and more important over time.
  • The Deadly Diamond Of Death In Java 9’s Module System discusses a problem Java 9 has with automatic modules, when a dependency has two names but one resolution path. (Confused? Read the article – it describes it better than I do, but at much more length.)

An Aside About Scala

A mailing list that was pretty popular back in the day recently had some activity asking about Java 8. The discussion itself was a little bit interesting, including a reference here and there to other languages… like Scala. Kirk Pepperdine wrote a post that absolutely riveted Your Humble Author, and may have actually convinced him to stop bothering with Scala except where absolutely necessary. I’d like to quote it here, since Yahoo!’s web page formats things poorly sometimes:

I personally don’t feel that Scala offers any advantages over Java. If you take away the opinions on style, I’d argue that moving to Scala actually leaves you at a slight disadvantage. First, point, the JVM support for languages other than Java was quite poor until Nashorn. Nashorn was actually 2 separate projects. One to get JS running in the JVM and the second was to refactor the JVM to isolate the APIs needed to support alternate languages. Scala hasn’t been able to take advantage of those changes as of yet and I’m not sure they are interested in doing so. Next is tool support. The Java tooling chain is and remains quite broken in 8. I fear that this situation will get slightly better in 9 but then changes there will batter the tooling china quite badly. Unless the Scala people step up to the plate (and there is no evidence of them doing so to date), the dismal state of the tooling chain in Scala will continue to get worse. I currently see very little motivation for companies to invest in the work needed to improve the tooling in Scala. Though I see that this might change, every time I’ve previously thought it might get better, something in the market changes and Scala takes a hit and things don’t get better so my track record on predicting this is admittedly very poor. But then I’m predicting improvements in this area and they’ve simply not happened.
What makes me more hopeful is that I know of a couple of very big projects running in stealth that are based on Scala. These projects are big enough that they’ve really been hurt by the weak tooling story in Scala and I imagine or can only hope that they will start to look at fixing the problems they are facing. Many of these problems are baked into the JVM so to fix them, we need to further fix the JVM’s support for alternate languages. The feeling I get coming from some JVM developers is that it’s the JVM that is past EOL. Maybe Graal will be the thing that replaced HotSpot… not sure… all I know is that the JVM is past due for a huge refactoring and simply don’t see anyone.. certainly not Oracle funding that effort.

I’ve “played”with the new features and to be honest find the Scala implementations cleaner and easier to write and understand.

To say that Scala is less verbose than Java maybe true in the small but I’ve found it not to be so true in the large. Reachability in a language is very important and deserved or not, Scala as the reputation of not being so reachable and hence not so readable. IME, almost everyone one I know struggles with the readability of Scala even those that have been using it for quite some time. This is not to say that Scala code can’t be read, it’s simply that Scala code not naturally easily readable and hence people struggle with it.
I think we had the same types of problems with Smalltalk. People resisted Smalltalk for some of the same reasons and in cases where C/C++ wasn’t so desirable we saw teams jumping to Java. In this era I think the current alternative to Java is Go. The buzz around Go is more marketing and hubris than reality but it has a buzz and level of activity that feels familiar to the buzz that we say with Java in it’s early days. Just like people kicked the tires and sniff around Smalltalk and then moved on, I get the same sense here with Scala.

Java is starting to give under its own weight of patched-on features, IMHO.

On the contrary, I think that Brian has done a wonderful job integrating Streams and Lambda’s into Java. The only thing I can complain about that makes things a wee bit difficult is this aversion to mutable state. Fine if you don’t like mutable state but that streams make the mutable/immutable decision is an overreach on Brian’s part. It disallows a valid model that we need to work in. It’s different than how everything else works in the language. Streams are inherently single threaded and thus concurrent modification of state is a concern that lies outside the internals of a Lambda expression. IOW, Java != Scala in that Scala had immutability baked into (just about) everything right from the beginning. Brian did consider these points when he designed Lambdas and he opted for his bias towards immutability.. so be it.. All I know if that Lambda’s do not feel like they are patched on to me. They feel like a natural part of the language… much better than the earlier proposals that were tabled. The work on ValueTypes and type inference is also focusing on making sure that the added features do not feel like bolted on bits and that they fit naturally into the current language. Brian’s idea was to create small changes in the language that have a huge impact on your code. While I don’t agree with all of his choices I do think he’s done a brilliant job.
Regards, Kirk

Interesting Links, 2017-Feb-2

Interesting Links – 2017-jan-23

  • Is it me, or is it actually ironic that the website for Rome (a utility library for RSS) doesn’t have an associated RSS feed?
  • The Log: What every software engineer should know about real-time data’s unifying abstraction, submitted by user whaley, is an excellently written article that discusses logs in the context of distributed systems – where the log is king, whether you use it or not. It’s a fantastic summary of distributed data processing from the standpoint of the technologies that the technique rely upon.
  • What Happens When You Mix Java with a 1960 IBM Mainframe which discusses a presentation by US Government employee Marianne Berlotti. In it, she describes Java having been used to serve as an integration layer between thoroughly modern technology and mainframes from the distant past (including providing a layer between JDBC and an IMS database – and for some reason, your author has a true fondness for heirarchical databases.) Neat stuff, even though the Java applications serve as performance problems in the architecture.

EJB Injection in JSP with Java EE 7

User suexec asked ##java about accessing an EJB from a JSP template.
User dreamreal (i.e., your author) put together a simple application (rather imaginatively called “suexec-war” ) to explore the possibilities. The application was built from Adam Bien‘s minimalistic Java EE 7 Maven archetype, deployed into Wildfly 10.0.
It turns out that to the best of my understanding, injection of an EJB into a JSP is simply unsupported. The JSP can use JNDI to acquire an EJB via JNDI (see source) but the CDI injection never worked.

Next, I wrote a simple servlet (called, of all things, TestServlet.java). Here, the @EJB MyEJB ejb worked like a charm.

To render, I used the Handlebars template library just for kicks; Freemarker (or even JSP itself) would have worked just as well, but I wanted to play with something different.
The process would have been the same no matter what templating library was chosen: you’d take the values you wanted to render and store them somewhere such that the rendering engine could access them. In my case, I could have built a composite object (or even asked Handlebars to call the greet() method itself, using the ejb value) but I was aiming for simplicity rather than optimal behavior, following whaley’s “Make it work, make it pretty, make it fast” principle (from “Suffering-oriented programming” )- this is rough code, meant to serve more as a smoke test than an actual example of a great application, so I left off at “make it work,” leaving even “make it pretty” to others.
Comments and improvements welcomed.

Interesting Links – 18 Nov 2016

Today’s apparently a Microsoft edition of the interesting links! Almost everything relates back to them this time…

  • From wyvern: “The Error Model” is an article discussing… exceptions. Exception handling and the “checked or unchecked” question is (still) controversial in Java; article provides some interesting context on error handling approaches, and explains how error handling evolved in Midori (Microsoft’s experimental research OS). A fundamental decision when choosing to make your API throw a checked or unchecked exception is whether or not a particular error is considered fatal or not. This is frequently a murky question: if you’re writing a one-off script, IOException may be fatal, but for a long-lived daemon, it should be handled safely and not rethrown to the top level. While we obviously can’t use Midori’s exact approach in Java, the thought process exhibited is helpful when deciding how to structure your APIs to allow tidy error handling. The whole Midori blog series is worth reading, if you’re looking for more.
  • Microsoft has announced that it is a Linux Foundation platinum member. My, how things have changed…
  • Speaking even more of Microsoft, it looks like they’ve finally open-sourced their SQL Server JDBC driver, and it’s hosted in a Maven repository. Typically, people use jTDS instead, but this is potentially great news; it’s not clear offhand what the advantages are compared to jTDS, but the more options you have, the better, right? Plus, this is another example of Microsoft actually contributing to the larger ecosystem, something many are still not used to. Now, if they could only make SQL Server less of a pain to work with…
  • Finally, stepping off the Microsoft train, user asgs pointed out Simon Ritter‘s “20 Years Of Java Deprecation,” which details the list of accumulated deprecated classes and methods in the Java runtime library. It’s actually a really low number given Java’s maturity (maybe that’s a sign of maturity?) — and it also points out that hardly anything is actually removed, although that will change with Java 9, with a whopping six methods being removed.

Interesting Links – 15 Nov 2016

  • Big news: JRebel 7 has been released, with a new agent enabling you to change class hierarchy and interface implementations on the fly. For Spring it now also supports reconfiguring dependency injection in non-singleton scoped beans.
  • From Light Java, “JEE is dead.” Misses a lot of history – blames Java EE for WebLogic’s speed and deployment model (what about containers like Orion, which could deploy the same apps in a few seconds, and didn’t need ejbc? What about JBoss, which was free? This post ignores both, saying Java EE containers were slow and expensive), and misrepresents a question about Oracle as a statement of Oracle policy, also misunderstands some other core facets – and tries to market Light Java itself as a framework, making this a bit of a “your framework is dead! Use mine!” post, but it’s still interesting. Of course, it’s not the only microcontainer framework out there in Java…
  • From /r/java, Jadler looks like a good HTTP mocking library.
  • Also from r/java, Nudge4j is a small jar to create a web-enabled access point for a running JVM – you can effectively type code to run inside a running VM. I haven’t tried it, but what an idea.
  • jsoup 1.10.1 has been released. Lots of little changes; the biggest seems to be the ability to preserve case of tags (as an optional feature) but memory usage has also been optimized.
  • John McClean posted an interesting article: “Trampolining: a practical guide for awesome Java Developers“.

Interesting Links – 8 Nov 2017

  • From ernimril: a video! CppCon 2016: Jason Turner “Rich Code for Tiny Computers: A Simple Commodore 64 Game in C++17” is an hour and twenty minutes of Jason Turner talking about writing a game for the Commodore 64 using, surprise, C++17 and translating to 6502 assembly. (Play at 1.25x speed to save some time – or 2x speed if you want that Brian Goetz effect.) It’s actually really fascinating to watch, and has nothing to do with Java whatsoever.
  • For Mac users, particularly on Sierra: “MacOS Sierra problems with java.net.InetAddress: getLocalHost()” documents some lookup problems on the recent MacOS update. Short form: make sure your /etc/hosts actually has your local domain name resolving to 127.0.0.1.
  • FindBugs is apparently having some problems.
  • Non-java, but useful for programmers anyway: Bulletproof Mind: 6 Techniques for Mental Resilience from the Navy SEALs. Some adult language, but it’s an excellent article and we’re all adults anyway.
  • Docker in Production: A History of Failure” is a litany of issues with the popular virtualization technology. It’s worth reading, even if you’ve deployed Docker successfully – if only to keep track of how far there is to go.
  • From the Python world: EAFP and LBYL. In Python, apparently using the “Easier to Ask For Permission” approach yields massive performance gains; Java, like C and C++, tends to prefer LBYL, which stands for “Look Before You Leap.” Worth keeping in mind, especially as Java adds more functional programming concepts. It’d be interesting to see EAFP and LBYL contrasted well in Java – and note that EAFP tends to prefer try/catch to manual boundary checking, so maybe Java’s already there to a large degree.

Interesting Links – 4 Nov 2016

Oh, boy, a bunch of releases:

  • Guava 20, the ultra-useful third-party library for Java that virtually everyone can and should be willing to use, has been released
  • MongoDB 3.4, the NoSQL document database used by jabavot and many others, has been released
  • LWJGL 3.1.0, the lightweight java graphics library, has been released

Finally, DZone publishes something I wanted to read:

  • Everything You Want to Know About ThreadLocal Random Implementation,” a really interesting walk through a random number generator.
  • From cheeser: Whiley, “A Programming Language with Extended Static Checking.” It’s another language for the JVM with significant whitespace (blocks are determined by indentation); it also provides a way for methods and functions to guarantee at the compilation stage that return values comply with a specification. It looks neat. It’s been around since 2009, and there’s no way to tell if it has any sort of path to critical mass yet. Take a look!