Symphonious

Living in a state of accord.

Better File System APIs

Dylan complained about the lack of testability with file system APIs, which reminded me of a neat looking library I stumbled across while looking at build systems: EntityFS. Among a bunch of other useful sounding things it provides:

File system APIs are backend-independent. File systems can be created in RAM memory, on Zip files, on file system directories, etcetera

Sadly it’s under the LGPL which makes it difficult if you happen to sell to big enterprises that are still somewhat scared of GPL type licenses, but they’re nowhere near as common as they used to be. I should note though that Holocene Software are offering commercial licenses for an undisclosed price.

The New Cross Platform

When I first started professional programming, Java was reasonably young and was being hailed as a work of genius with it’s cross platform deployment capabilities. Programming was going to be revolutionised forever and all programs would run on any OS1. Then Java wound up being most popular on the server side and liberated server code from the choice of OS more than the desktop side2.

Server OS’s started to compete mostly on how well they were a server rather than what programs ran on them because what really mattered was that you could run the Java stack. In other words, Java became the platform that people deployed their applications to. It shouldn’t come as a surprise that a single platform didn’t stand unchallenged for long. .NET sprang up as the big enterprise competitor to Java and all of a sudden you had to choose sides again.

The interesting thing is that another layer of platform abstraction is starting to spring up. Languages like Ruby and Python came from a background of running standalone and are now starting to abstract away the choice of the Java or .NET platform, just as Java abstracted away the choice between Linux, Windows or Solaris in it’s time.

From what I can tell, none of the languages have really developed a fully complete, heavy production ready, bet-the-company-on-it implementation for both the JVM and .NET but both Ruby and Python seem to come very close and have serious corporate sponsorship behind them. Right now the sense I get is that people are either using Iron Python or Jython, Iron Ruby or JRuby but not seriously deploying the same code to both. It doesn’t look like it will be long before doing so would be quite feasible though.

Exciting times ahead.

1 – Interestingly enough this has actually been the trend, but not because programs were developed in Java – it just inspired developers in other languages to build cross-platform abstraction libraries.

2 – albeit not as smoothly as anyone would have liked

I Love Parser Generators, I Hate Parser Generators

Parsers drive me mad.I was reminded on the weekend of how much I like working with parser generators – they’re just so pure and clean. You really feel like you’re working with a grammar and all those CS lectures come flooding back. Writing code to parse the same content by hand just never has that feel. Plus they create incredibly accurate parsers in very little time at all.

I was also reminded of how much I hate parser generators. They generate very accurate code which is great when you have very accurate input. In the real world, it just means the parser craps out an awful lot on very minor syntax problems. So then you try to make the grammar more flexible to accept that input and the generator just complains that the language is no longer LL(1).

Off we go into the deep dark depths of those CS lectures. Now all of a sudden you find yourself with pen and paper out drawing states and the paths between them. Pretty soon you want to migrate to A3 paper and then on to butchers paper. Eventually you find yourself writing on the wall.

Real world content just isn’t sane. You can’t tokenize it first and then just use those tokens – characters in different places have all kinds of different meanings. You don’t really want to validate the content as you read it1, you just want to do the most brain dead simple thing to get that content in and in a form that you can work with2.

I run into this every time I work with parser generators and wind up spending so much time making the grammar fully tolerant that it winds up being easier to just write the entire thing by hand. I just can’t help but think that there should be a better way though.

1 – beyond making sure you’re avoiding buffer overflows and that the resulting model isn’t dangerous etc but often those kind of checks are best done in the code that actually does the work (i.e. assume every value is user supplied rather than assuming that the content is all nice and safe).

2 – this of course is situation dependent. I happened to be parsing CSS where tolerance is the key to success. Parsing configuration files on the other hand should be strict and fail fast.

Install the MSN Toolbar With Java?

So Microsoft has provided handy instructions for upgrading Java which is nice of them – especially since IE 8 doesn’t play nice with versions of Java before 1.6.0_11. Step 6 suggests installing the MSN toolbar along with Java though:

In addition to Java, you can also install the MSN Toolbar. The MSN Toolbar offers headlines, news alerts, and search tools from Microsoft. For more information see the MSN Toolbar home page. To install the toolbar, click the Terms of Use or Privacy Statement buttons and then read the statements. If you don't want to install the toolbar, clear the Install the new MSN Toolbar check box.

The odd thing is, last time I installed Java (this morning) it was the Yahoo toolbar that Java tried to install along the way. I guess Sun will give kick backs to whoever sends them traffic…

Debugging Deadlocks – Print All Stack Traces

One of the hardest types of bugs to track down is a deadlock situation. They are very time dependant which makes them intermitten, specific to a particular computer and configuration and generally impossible to reproduce in a debugger. Fortunately, at least in Java, it’s fairly easy to spot most of the situations where a deadlock is possible:

  1. Calls to SwingUtilities.invokeAndWait
  2. Calls to Object.wait()
  3. synchronized blocks

There might be a few others depending on the libraries you’re using, but starting with those three, in that order, is very likely to lead you to at least one point in the deadlock.  Just put an old fashioned System.err.println before and after each of those calls and you’ll quite quickly see where things are waiting forever.

Deadlocks have to have at least two threads involved. To find the other one, you need to print the stack traces of all the other threads immediately before you actually hit the deadlock.  So once you’ve found one call that’s part of the deadlock, add a call to the method below just before it.

private static void printAllStackTraces() {
    Map liveThreads = Thread.getAllStackTraces();
    for (Iterator i = liveThreads.keySet().iterator(); i.hasNext(); ) {
      Thread key = (Thread)i.next();
      System.err.println("Thread " + key.getName());
        StackTraceElement[] trace = (StackTraceElement[])liveThreads.get(key);
        for (int j = 0; j < trace.length; j++) {
            System.err.println("\tat " + trace[j]);
        }
    }
}

You’ll get a whole bunch of threads and with a bit of digging around to see exactly what the code is doing in each thread you’ll probably find a pair of threads like below that are waiting on each other (package names removed to make things shorter):

Thread Thread-14
 at Object.wait(Native Method) at java.lang.Object.wait(Object.java:474)
 at EventQueue.invokeAndWait(EventQueue.java:848)
 at SwingUtilities.invokeAndWait(SwingUtilities.java:1257)
 at CachingFileDownloader.run(CachingFileDownloader.java:204)
 at WorkerThread.run(WorkerThread.java:49)
Thread AWT-EventQueue-2
 at Object.wait(Native Method)
 at Object.wait(Object.java:474)
 at CachingFileDownloader.waitUntilDownloadComplete(CachingFileDownloader.java:290)
<snip>

Yep, the swing thread is waiting on the download and the download thread is trying to do something on the swing thread via invokeAndWait. It’s actually trying to close the download progress dialog which can most likely just use an invokeLater, thus avoiding the deadlock.

This is also a really good example of why I put SwingUtilities.invokeAndWait at the top of my hit list. Also, the actual call to invokeAndWait that I put the debugging above, wasn’t really involved in the deadlock, it just happened to need to wait on the Swing thread as well and wound up waiting forever because the other two threads were deadlocked with each other.

As a side note, I think this is the first time since we started publishing the twice daily builds to my blog automatically that I’ve had a catastrophic failure where I couldn’t post at all. That’s not a bad run considering it’s been at least a couple of years living on the edge.

Sigh, and upon hitting save I find that the debugging code I added above can cause security exceptions when triggered as part of our form submission process in Safari (but not FireFox) on OS X. So if you originally saw this post with no content, that would be why…