Friday, July 25, 2008

Obligation analysis: success!

The implementation of obligation analysis in FindBugs seems to be in a useful state.

The analysis found about 8 bugs related to unclosed streams in FindBugs itself. If you write tools to find bugs, people always ask you if the tool finds bugs in itself. Well, FindBugs certainly does on a regular basis.

I analyzed Vuze (formerly Azureus), and the detector reported 35 warnings. Of those warnings, 17 appear to be legitimate issues, and another 17 are probably benign warnings that could be eliminated through the use of the JSR-305 @WillClose or @WillCloseWhenClosed annotations. (These annotations are used to specify methods and objects that assume responsibility for closing a resource.) 1 warning was essentially a duplicate of another (apparently correct) warning.

Analysis of jEdit was not quite as impressive, but still interesting: 4 apparent bugs, 9 warnings about probably-correct code that could be eliminated by annotations, and 3 cases where the analysis was wrong. (I need to investigate the last category.)

One type of false positive the paper didn't mention (that I can recall) was when one resource object "wraps" another. This, of course, is a common design pattern (Adapter) used in the java.io package.

Example:
InputStream in = new FileInputStream(filename);
Reader r = new InputStreamReader(in);
try {
...
r.read()
...
} finally {
r.close();
}
The analysis assumes that the InputStream is the obligation needing to be cleaned up, but the finally block closes the Reader instead.

The @WillCloseWhenClosed annotation would fix this problem (explicitly specifying the "transfer" of one obligation type to another), but since JSR-305 is not official yet, the standard Java classes don't use this annotation.

I worked around this issue by having the detector find likely places where an obligation transfer occurs, and then checking to see if the unmet obligation can be explained by an obligation transfer. This heuristic seems to work fairly well in practice.

Interestingly, a similar issue occurs when the "wrapped" resource is closed instead of the "wrapper". Technically, this could be considered a bug (the "wrapper" resource's close() method might have extra work it wants to do), but in many cases this is also a correct approach. The same heuristic (looking for probable obligation transfers) seems to be effective.

Thursday, July 17, 2008

Don't use the Intel CPU fan

I have built two systems using Intel socket 775 CPUs recently. Last summer, I built one using a Pentium Dual Core E2140 (1.6 GHz), which I use at school. This summer, I built one using a Pentium Dual Core E2220 (2.4 GHz), which I use at home.

Putting together the newer one, I managed to break off one of the "legs" of the stock Intel CPU fan. So, I bought a cheap third-party CPU fan at a local computer store. The older system I use at school has the stock Intel CPU fan installed.

Interestingly, my home machine runs much cooler than the system at school. Even under load, neither core gets above 45C, and each core idles around 30C.

The system at school idles around 45C, and reaches close to 60C under load, even though the CPU is running nearly 1 GHz more slowly than my home machine. Each machine has a cheapo ATX case with a case fan (in addition to the power supply fan.)

This strikes me as odd: if you follow Intel's installation instructions exactly, you get pretty inadequate cooling. I know the customer reviews on newegg always say that the Intel CPU fans suck. Well, I guess they do!

Monday, July 14, 2008

Obligation analysis

A common form of runtime error in Java programs is not closing or freeing an acquired resource on all paths out of a method. This kind of error is especially common with i/o streams, but also affects database resources, JSR-166 lock objects, etc.

FindBugs has a couple detectors that I wrote quite a while ago for detecting such errors. The detectors use a rather ad-hoc analysis, and produce a variety of annoying false positives.

Wes Weimer and George Necula proposed a nice static analysis to find such errors at OOPSLA 2004. I am finally getting around to getting this analysis implemented in FindBugs. Their analysis tracks obligations (open streams, db connections, etc.) on (effectively) all acyclic paths through methods, the basic idea being that every acyclic path ought to discharge all of its obligations. The analysis does not attempt to track the actual resource values through variables and heap locations. Instead, it just checks that each resource acquisition reaches an appropriate resource de-allocation.

I think I have finally gotten to the point where I understand how the analysis works, and the initial implementation in FindBugs seems to be working. I still need to complete the database of method calls which create or discharge obligations, and also implement several post-processing steps for false positive elimination, but I don't think this will be a huge amount of work.

Friday, July 11, 2008

Ruby on Rails in Netbeans

Netbeans is slowly becoming my favorite IDE. (Sorry, Eclipse!)

Today I started using the Ruby on Rails support within Netbeans, and it's quite nice. I'm probably not doing anything terribly sophisticated, but I did manage to create and run migrations, create some controllers and views, and launch the app, all from within Netbeans. Eclipse probably has support for all this stuff, but due to unexplained Eclipse crashes (on Linux), I can't actually use it.

I'm using the JRuby plugin for Netbeans, which means my rails code is actually running in Java. Kinda nice - Java is a more ubiquitous runtime environment that Ruby, so I'm thinking this will be helpful when it comes to deployment time.

Monday, June 9, 2008

Eclipse weirdness, NetBeans to the rescue

Last week, I did a hardware upgrade on my home PC. Originally, I had an EliteGroup 848P-A motherboard with a Pentium 4 2.8GHz (Prescott) with 2 GB of DDR 400 RAM. The new configuration has a Gigabyte GA-P35-S3G motherboard with a Pentium Dual Core E2220 (2.4GHz) and 4 GB of DDR2 800 RAM. It was a pretty cheap upgrade, and performance on compute-intensive tasks seems to be about 2x faster. Kubuntu 8.04 recognized all of the new hardware; no reconfiguration was necessary.

Weirdly, there is one important application that no longer works following the upgrade: Eclipse. I get repeated segfaults in libjvm.so. As far as I can tell, it's not a hardware problem. All other applications I have tried have been 100% stable, my CPU temperature has not exceeded 41 C for either core, memtest86+ did not find any problems with the memory, etc.

So, I conclude that it's some sort of software problem. Could it be a weird interaction between SWT and gtk+? This is where native code really sucks.

In the meantime, I'm using Netbeans for Java development. It's gotten quite a bit better since the last time I used it. It's maybe not quite as polished as Eclipse, but the important features (code completion, cross-referencing, and refactoring) are there.

Thursday, May 29, 2008

Summer!

Hooray, it's summer! (I define summer as the period of time between Spring and Fall semesters, not by the progress of the earth around the sun.)

I'm setting up my home machine to do some work on FindBugs over the summer, and since my Ubuntu 6.10 was getting a bit stale, I decided to upgrade. I happened to have a CD burned with Kubuntu 8.04, so I backed up my essential files and let the installer rip. So far, it seems nice. It took a bit of getting used to KDE rather than GNOME. Overall, KDE seems less polished than GNOME, but more configurable. I'm using Amarok to play my music files, and it appears to be significantly better than Rhythmbox. (See previous post to see my ranting about how much I dislike Rhythmbox.)

Out of curiosity, I installed the Ubuntu openjdk package, and tried running Eclipse on top of it. So far, it seems to work quite well! It's exciting to finally have a usable free Java implementation. Major kudos to Sun for open sourcing the JDK.

There is a weird bug on Ubuntu/Kubuntu 8.04 with Eclipse: here is the bug report. The workaround described in the bug report does seem to fix the problem.

I bought a new monitor, an Acer AL1916. Newegg was having a special for $159, with free shipping. Now (at long last) both of my monitors are the same size and resolution.

I finally started some work on FindBugs today. First project: implementing exclusive type qualifiers. (This is part of implementing support for JSR 305 type qualifiers in FindBugs.) Bill Pugh has a nice presentation about JSR 305 which explains all of the goodness.

Tuesday, May 6, 2008

Rhythmbox

I've been using Rhythmbox for a while to play my music files (which are, of course, in Ogg Vorbis format.)

I hate to say it, but I have become so frustrated with Rhythmbox that I'm now actively looking for a replacement. Here are my main gripes:

Gripe #1: When you toggle between the "small display" and the full size display, the window size chosen is always wrong. What I expect to happen is that whatever window size I configure in the two modes, Rhythmbox will remember my decision. For f***'s sake, would this be so hard to implement? Here's what actually happens: when switching from the small display to full display, the full display gets a hard-coded height of about a third of my display height. Here's a screenshot:

As you can see, the various lists (artist, album, tracks) are completely squashed. THIS SUCKS!!!! (As a bonus bug, you'll notice that in Ubuntu 7.10, gimp is no longer able to capture screen shots that include the window decorations.)

When switching from the full display back to the small display, sometimes the size is restored correctly, and sometimes the width of the full display is preserved (meaning that you get an extremely wide small display):

Nice work, rhythmbox!

Gripe #2: When an album finishes playing and you click "Play" again, it starts playing from the last track, not the first. Yeah, that's just what I wanted to do.

Gripe #3: If you click "Previous" too quickly, playing stops altogether, even if you haven't reached the first track yet.

One of the reasons I have been an enthusiastic user of free software over the past 15 years or so is that it generally places a high value on correctness and utility over bells and whistles. It concerns me greatly that the free software world is moving towards a Windows model where every application is skinnable, animated out the wazoo, has a feature list the size of a telephone book, and is impossible to use for more than 2 minutes without uncovering a serious bug.