Sunday, October 15, 2006

Code Advice #14: Don't initialize fields to default values

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


(See intro for a background and caveats on these coding advice blog entries.)



If you've been coding in C, you've probably picked up the habit of initializing all your fields:


char *foo = NULL;
int bar = 0;




This is necessary, because in C, memory can be left uninitialized, so there's no telling what value foo will have before it is assigned something.



In Java, however, the language specification clearly defines default values, so virtual machines will for example always initialize reference fields to null.



Specifically, this means that code like the following is redundant:


private int foo = 0;
private Bar bar = null;
private boolean baz = false;




The alternative form of initializing the fields explicitly in the constructor, is the same:


private int foo;
private Bar bar;
private boolean baz;

public Foo() {
foo = 0;
Bar bar = null;
baz = false;
}



You can leave out the above initializations, and the program will behave the same way. Carl Quinn once convinced me that this was more readable, so I picked up the habit, and I now swear by it. On the one hand, you can argue that leaving the explicit initializations in is more readable because you're making it really clear what it is you are intending. On the other hand, Java programmers quickly learn what the default values are and understand that an uninitialized field is the same as a nulled out field.



It turns out that the two forms are not exactly identical! If you disassemble the above code, you'll find the following bytecode is generated:


4: aload_0
5: iconst_0
6: putfield #2; //Field foo:I
9: aload_0
10: aconst_null
11: putfield #3; //Field bar:LBar;
14: aload_0
15: iconst_0
16: putfield #4; //Field baz:Z



If you leave out the initializations, none of the above bytecode is generated. In a simple microbenchmark there was a measurable time difference (about 10%) for the case where a handful of fields were initialized versus leaving them uninitialized, so it's clear that Hotspot doesn't completely eradicate the differences here. (<speculation>Perhaps it just zeroes out the whole object memory block when allocating a new object, relying on the default values to all be represented as zeroes natively, and this is done even when all fields are later initialized?</speculation>)



Obviously, speed considerations is not what should be the deciding factor here. This was a microbenchmark doing nothing other than construct objects with and without initialization - it's unlikely that you'll find a measurable difference on a real program. What really matters is readability. I should also point out that Findbugs will treat these two scenarios differently. If you print out a field value in the constructor, it will warn about an uninitialized field if the field was not explicitly initialized in the field declaration.



I can see arguments both for and against explicit field initialization, but I think this is one of those cases where convention wins. I personally find code cleaner and more readable when you leave your fields with implicit rather than explicit initialization.



P.S. Remember that null fields are often a bad idea and should be initialized to null-objects!


Tuesday, September 26, 2006

NetBeans Plugins I Use, Part 5: Build Monitor

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


(Parts
1,
2,
3, and
4.)



The Build Monitor plugin for NetBeans allows you to see the status of continuous builds, right from within the IDE. The Build Monitor works with several continuous build systems - CruiseControl,
Hudson,
and of course the NetBeans continous build.
You can monitor multiple build sources - all you do is name your build and point to an RSS feed where the plugin can fetch the build status. Each build is then displayed right in the IDE status bar. You can set the polling frequency yourself; I've set mine to check every minute! Here's what this looks like:





This is obviously what you don't want to see - while the NetBeans continuous build is fine, the second continuous build is currently failing, as indicated by the red ball. In this case, just click on it to open the browser for the corresponding build status page - where you can for example click on the Console Log to see the build script output.






You can grab the Build Monitor plugin from the Beta Update Center, or from nbextras.org.



Yesterday, I set up a continuous build for the project I'm working on. It was really simple. All I had to do was download
glassfish, run its setup script, download Hudson, and drop the hudson.war file into the autodeploy directory in Glassfish. Then I just went to localhost:8080/hudson and from there I could set up a build using a simple web interface. I just needed to point to my CVS server (Subversion is supported too) and my ant scripts, and voila - continuous builds. If you want to take a look at what Hudson looks like in action, visit this page where you can see Glassfish itself being built in a Hudson setup.



Tips:


  1. It's a bit tricky to configure the build monitor. The trick is to open the options, then go to the Advanced Options, locate the Build Monitor item, right click on it, choose new build monitor. Then set the RSS feed to the build failure (or all builds) feed you want to use - Hudson displays it right in the status page.

  2. I had to restart the IDE before the build monitors showed up in the Status Line. We should set the needs-restart property of the auto update bundle.

  3. I had problems using the most recent snapshot of Hudson so I grabbed a slightly older version and things were fine.




Thanks to Tom Ball and Jesse Glick for this plugin.


Wednesday, September 20, 2006

Working with classes that (unfortunately) call overridden methods from their constructors

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


I was struggling with a problem today, and I found a pretty decent workaround. Since initial googling hadn't turned anything useful up, I figured this writeup might help others who search for it in the future.



In essence, the problem boils down to "How can you initialize your own object before the superclass constructor has run?"



Let's express this in code - I've changed the example to a simple domain to make the intent obvious:



/** Represents a building, such as a house, a garage, etc. */
public class Building {
public Building() {
// Do something with the result of getColor(), such as
reservePaint(getColor());
}

protected abstract Color getColor();
}


The above class is the "framework" class I'm trying to extend. I do not have the option of changing it or extending something else; this is the integration point.



Note the error above: the constructor is calling an overridden method. This is a
well
documented
problem. Previous uses of the above class had probably not run into it, because most usages would be something like the following:


public class Skyscraper extends Building {
protected Color getColor() {
return Color.LIGHT_GRAY;
}
}


Since the overridden method typically returns a constant that is independent of the subclass object being properly constructed, calls from the superclass constructor did not cause problems.
The problem was that in my case, I'm dynamically constructing many different types of Buildings, so I want to parameterize the getColor() method:



public class PaintedGarage extends Building {
private Color color;

public PaintedGarage(Color color) {
this.color = color;
}

public Color getColor() {
return color;
}


Unsurprisingly, this fails at runtime.
(When you construct the PaintedGarage object, the superclass constructor, Building(), will be called before the PaintedGarage constructor is called, and when it
calls the getColor() method, it will read the color field which has not yet
been initialized.)



With that long motivation: What can we do about this? Following the Effective Java practice of not calling overridden methods from the constructor is not an option. Remember, that is done in the superclass, and that is a class we have no control over - it's part of the framework we are plugging into.



In an earlier version of this, I was already computing classes on the fly (using a byte code generator library), so it was simple for me to simply inline the literal return value in an overridden version of getColor.



However, I no longer need to do that for other purposes, so is there a way for me to ensure that getColor gets initialized by the time the super class constructor calls it?



Yes!



The trick is to use an inner class. The process is as follows.
First, file a bug against the framework you are using to get the constructor behavior changed.
Second, try something like this:



public class PaintedGarageFactory {
private Color color; // Moved out of PaintedGarage and into enclosing (not super!) class

private PaintedGarageFactory(Color color) { // Use factory method below
this.color = color;
}

class PaintedGarage extends Building {
public PaintedGarage() {
}

public Color getColor() {
return color;
}
}

public static PaintedGarage create(Color color) {
PaintedGarageFactory factory = new PaintedGarageFactory(color);
// Notice how the outer class is fully constructed before the
// inner class (and its superclass constructor) is built.
// Each factory instance constructs PaintedGarages of a particular
// color (and could be reused etc.)
return factory.create();
}

private PaintedGarage create() {
return PaintedGarage();
}

}


What this has done is move the parameters that need to be initialized before the superclass
constructor is run, out to the outer class. These are obviously initialized before the innerclass
is constructed.



This is not a good way to write code, but it solves the immediate need: You've
provided an implementation of the super class that is properly constructed as far as the
superclass constructor is concerned.



Don't forget to get the framework fixed.


Monday, September 18, 2006

Tabs Are Evil, Part 3

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


For part 2, see here.




We've got a new

forum
set up for the Java Posse. There's quite a bit of activity there already. One entry in this thread argues once again that there is nothing wrong with tabs and that they are a good way to express indentation.
(We keep mentioning that Tabs Are Bad on the show). I've gotten similar feedback from my previous anti-tab blog entries.



A couple of weeks ago I was taking a look at the findbugs source code, and here's what I saw:






Findbugs follows a coding style where it uses tabs for indentation. In the above you can see that the tabs are really standing out since I have them highlighted with the NetBeans fixtabs module.



The thing to notice is that there are lines where spaces are (probably accidentally) used for indentation. For example, line 2, the beginning of the method signature. And also on line 3, where there is first a tab, then eight spaces, to indent the throws clause.



If this source file is interpreted with tabs expanded to anything other than 8, the code will not be aligned properly. And this is precisely what is problematic about Tabs. Tabs, in most editors, are visually indistinguishable from spaces. Thus, when you're editing, you can't tell that you've accidentally just indented a line with spaces. Obviously, developers might do this by accident, since they already hit the spacebar to insert whitespace between symbols. You can't have the IDE automatically insert tabs instead of spaces. But you can certainly do the opposite. And if you do, you'll avoid problems like these.


Thursday, September 7, 2006

Welcome JRuby

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


Sun has hired the two primary JRuby developers,
Charles Nutter and
Thomas Enebo.
This is great news for JRuby, because it will now be their full time job to work on it.
(JRuby is an implementation of the Ruby language that runs on top of the Java platform.)



This obviously fits well with our strategy to support multiple languages on the JVM, and in particular,
dynamic and scripting languages. In fact,
Charles and Thomas is joining the group I'm in, so hopefully a lot of the tool support we have built to support BASIC will also benefit JRuby. Going forward there will probably be a lot of cross pollination.



Welcome to Sun, Charles and Thomas! Charles has already blogged about joining Sun.





Friday, August 25, 2006

Creator On Speed, Serious Speed

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


Hotfix 2 has been released for Creator. The focus of this patch release has been performance, and there are some significant gains.
Here's
one testimonial from the Creator forum after the bits were released this morning:


This is awesome. I have experienced orders of magnitude improvement in performance - specially building and deploying the apps. It used to take 3 mins., now it takes less than 10 secs.


The main performance fixes were in the source modeller, so project open and editing is where the speedups are to be found.
Sakhti Gopal in Creator QA has done a lot of analysis of the performance improvements and provides further details on the improvements. Opening pages, switching from source to design view etc. is at least twice as fast, and in many cases several times faster.



The Tutorial Divas on the Creator team also provide coverage; they've measured various tasks on a moderate project, and as you can see the performance improvements are dramatic. They are using percentages rather than speedup factors. What is a 97% improvement? Some people think of "100%" improvement as doubling something (or when appropriate, halving something). But here it means that it was reduced by 97% of the original amount; thus it is the same as a 32x speedup!! Adding a table to the first page for example used to take 16 seconds, it now takes 4 seconds - a 4x speedup.




If you've been using Creator 2 and have been dissatisfied with the performance (you were not alone), hopefully this will make you much happier. If the earlier performance turned you off from Creator 2, give it another chance. This is not the end of the performance work for Creator; a larger rearchitecting of the Java source model in our tools is being performed as a foundataion for NetBeans 6.0 (to also accomodate a lot of new cool Java source editing features). In the next Creator generation, this will allow Creator to be a lot more efficient both in CPU and memory usage. Today, Creator does not use NetBeans' source model; it has its own, which means there are two source models that need to be kept in sync. What Hotfix 2 did was ensure that this syncs are only done when necessary. And what a difference it makes!



How do you get it? Use the Update Center in Creator. If you don't have direct internet access from your Creator installation, you should be able to download the update by following links from the Creator site.



Thursday, August 24, 2006

More on Nullness

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


The other day I
wrote about using annotations to state your intent regarding null for fields, parameters and return values. This can help static checkers like
findbugs find flaws in your code, where you fail to check return values for null where that is known to be risky. (In fact, findbugs does not only base knowledge of nullness on your use of annotations; it also has a builtin database of system API null behaviors, since these classes have not been "instrumented" with nullness annotations yet.)



I did however mention one big problem: These annotations are not (yet) standard - so you'll need to choose to use them from somewhere - and add third party imports to all your source files, add a foreign jar to your build, etc. Findbugs' set of annotations is probably as good a candidate as any. But while the annotations are licensed under LGPL, which should be fine for most of us, some companies (or at least their lawyers) are weary of mixing GPL anything with proprietary code.



Our lawyers are generally fine with LGPL usage, but I was still wondering if there was a way I could "isolate" myself by using an annotation from my own project, and then somehow tie that to a standard annotation in a single place. If annotations were like classes this would be easy - I could simply extend the findbugs one and I'd be done. But annotations don't work that way. So I thought I'd take a look at findbugs internals and see what's going on.



And I was surprised, and happily surprised at that, to discover that findbugs is very tolerant in how it deals with nullability annotations. It is not favoring its own annotations. In fact, all it checks for is whether the annotation base name matches the name findbugs has chosen. This was probably done deliberately, to ensure that findbugs works with code annotated for other tools, such as IntelliJ. This is really a great idea - and it doesn't seem risky to me; I can't think of many other uses for an annotation named "CheckForNull" or "NonNull". Of course, if a problem ever arises they can always update findbugs to be more discriminating for users who want to use home grown annotations where those names mean something else.



So, you can simply define your own project wide nullability annotations (they are simple marker annotations with no members), and then findbugs will happily do its magic. Worked like a charm for me:






Null Handling: Much ado about nothing, literally.



P.S. For more about the built-in set of null knowledge of Java standard APIs, see the class NullnessAnnotationDatabase in the findbugs source distribution (which handily comes distributed as a NetBeans ant-based project - thanks!)