Monday, July 28, 2008

Obligation analysis data

Here are the FindBugs analysis results files for my recent use of obligation analysis to look for unclosed stream bugs in Vuze and jEdit:

I classified the warnings as NEEDS_ANALYSIS if I considered the code apparently correct, and the warning could be avoided through the use of annotations (@WillClose, @WillCloseWhenClosed, etc.) These were cases where if a called method (or object) failed to close the stream, then there truly would be a bug.

I classified warnings as SHOULD_FIX if I considered that it was possible for the code to fail to close a stream.

I classified the warnings as ANALYSIS_ERROR if the warning was completely erroneous.

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 package.

InputStream in = new FileInputStream(filename);
Reader r = new InputStreamReader(in);
try {
} finally {
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.