Pure Danger Tech


JavaOne: Java Puzzlers Shlock and Awe

02 Jun 2009

Neal Gafter and Josh Bloch are back for another edition of Java Puzzlers, even more puzzling than before. As always, a good show. I’ll warn you that if you hope to watch or listen to this talk later on, I’ll be spoiling all the fun here. :)

Puzzler 1 – I didn’t catch the name of Puzzler 1 as I was filing in still, something about the simple questions. It boiled down to a call to the somewhat obscure method Boolean.getBoolean(). This might appear at a glance to parse a string and return a boolean but in reality it reads the System property for which you give a name and parses that return value as true or false.

The lesson from API design here is that this method is totally in the wrong place (buried in a low-level wrapper class) and similarly named to other “parse” type methods in the other wrapper classes.

Puzzler 2 – Instruments of Torture – this puzzler centered around a subclass of HashSet called InstrumentedHashSet that counted all adds by overriding both add() and addAll() methods and counting before forwarding to the super class.

In this case the bug was that inside HashSet, addAll() calls add(), which means that your counts will be screwed up. The lesson is that when wrapping a class like HashSet you shouldn’t make assumptions about how it works internally.

They then showed a nice rewrite using a ForwardingSet that simply forwards to a decorated implementation. ForwardingSet (and it’s ilk) are included in the Google Collections library.

Puzzler 3 – Iterator Titillator – this example concerned the implementation of an AbstractIterator that could be used to more easily implement iterators by just relying on a nextElement() method.

It was all a set up to show the issue around having a constructor call a method overridden by a subclass. If that method mucks with state held in the subclass, it will be modified before the subclass’s initializers are called, meaning that those state changes are lost.

I clearly remember the first time I hit this (probably buried in some template method code) and bashed my head on it for several hours and even filed a Java bug on it (which was of course rejected). Definitely a good learning experience.

They said Brian Goetz did this twice in a single week so there is comfort that we’re all mortal.

**Puzzler 4 – Searching for the One</strong - this puzzler had to do autoboxing and comparators. There were actually a couple of interlocking issues. One had to do with using Integer.valueOf(String), which does not use the interned autoboxed wrapper objects but always returns a new instance. The other had to do with an equality comparison between two Integer objects in the comparator. </p>

Turns out that the puzzle masters themselves screwed this up in the first edition of the Puzzlers book.

Puzzler 5 – Cogito Ergo Sum – this implementation had to do with a RomanNumeral enum implementation where the enums were being added to an internal static map. The primary issue was that the enum constant initialization is done as static constants before the map was even initialized. This looks like it should throw a NullPointerException but because of where it occurs it manifests as an ExceptionInInitializerError. The fix was to use a static { } block instead and construct the map after the constants were created by enumerating through values().

Puzzler 6 – Thread friendly – this one had to do with a ThreadLocal that was holding instances of a non-static inner class. The value in the ThreadLocal (the non-static inner class) has an implicit “this” reference back to the outer class, which subsequently holds a reference to the key. Thus, the ThreadLocal (which is implented as a WeakHashMap) will never release any objects and that causes a memory leak.

The puzzle-masters mentioned that even Bob Lee (the reference master himself) made this mistake in the Google ad server, killing it due to a memory leak. Again, comfort for us mortals.

**Puzzler 7 – When Worlds Collide</strong - this one was a little recompilation puzzler where a class with some constant values was changed and recompiled and run with a wrapper program (that wasn’t). Compile-time constants are of course compiled into using classes. The puzzle was that a null value in the original version is NOT a compile-time constant and is not inlined, which resulted in a mixture of the non-null constants from the first version and the new value from the second version. The lesson here is that null and enum values are NOT compile-time constants, and not inlined. They also showed that it is trivial to avoid inline constants by just adding a method that returns it’s parameter and passing the values through the method. </p>