Stupid Things to do in Java #1

Here’s the first post, in hopefully what will be a relatively infrequent series. It’s going to cover stupid things I’ve done in Java, so you won’t make the same mistakes.

In this first post I’m covering a scenario where I was getting a NullPointerException on a field that is initialised on construction, i.e. it should never be null. Below is a set of classes that recreates the situation (I don’t know if it compiles or runs), see if you can spot the mistake:

public class X {
    private String someVar;

    public X(String someVar) {
        this.someVar = someVar;
    }

    public void doSomething() {
        // Does something with someVar
        this.someVar.length();
    }
}   

public class Y extends X {
    private static final Y INSTANCE = new Y();

    private static String SOME_CONSTANT = "blah";

    private Y() {
        super(SOME_CONSTANT);
    }

    public static Y getInstance() { 
        return INSTANCE;
    }
}

public class Main {
    public static void main(String[] args) {
        Y y = Y.getInstance();
        y.doSomething();    // NullPointerException happens here
    }
}

Did you spot it? In this example X.someVar will always be null because Y.INSTANCE is created before Y.SOME_CONSTANT, meaning doSomething() will throw a NullPointerException. It’s an odd bug because it makes you think about class initialisation and mixing static and non-static fields in your class. My mistake was thinking that constants (i.e. static final fields) are always set before you can instantiate a class, but in this example you can use it before it is set. I don’t think the compiler catches it because the first use of SOME_CONSTANT appears after it’s definition, but the declaration of INSTANCE jumps ahead of it causing the problem. So if you have a singleton, make sure you create it after the rest of your static fields.

Update 1: Dmitry spotted a couple of bugs in my code, and one that in fact shows the above case cannot happen. A variable declared as static final always gets initialised first, so the code I was working on must have omitted the final declaration hence causing the NullPointerException.

Update 2: I’ve modified the code above to now break as I described since some people are running it. See the comments for explanations on the full set of conditions for this bug to occur.

Spread the word: Technorati related  |  Technorati related  |  del.icio.us bookmark it!  |  submit Stupid Things to do in Java #1 digg.com digg it!  |  reddit reddit!

5 Responses to “Stupid Things to do in Java #1”

  1. David Grant says:

    So are you saying that when “new Y()” is called, SOME_CONSTANT is set to null at this point, and in the private Y() constructor it passes null to the super? Are you also saying that flipping the order of the two statics around fixes it?

    private static final String SOME_CONSTANT = "blah";
    private static final Y INSTANCE = new Y();
    
  2. Miles says:

    Yes, that’s the problem, SOME_CONSTANT is null when new Y() is called. Flipping the order does fix the problem.

  3. Dmitry says:

    The key thing in this post is ” I don’t know if it compiles or runs “.

    The code does not compile because getInstance is not “static”.
    This is from Java Language Specification on static variables:
    8.3.2.1 Initializers for Class Variables
    One subtlety here is that, at run time, static variables that are final and that are initialized with compile-time constant values are initialized first. This also applies to such fields in interfaces (§9.3.1). These variables are “constants” that will never be observed to have their default initial values (§4.5.5), even by devious programs. See §12.4.2 and §13.4.8 for more discussion. Use of class variables whose declarations appear textually after the use is sometimes restricted, even though these class variables are in scope. See §8.3.2.3 for the precise rules governing forward reference to class variables

    So to get your situation to produce a null pointer you will need to remove a “final” from SOME_CONSTANT field and add “static” to Y.getInstance()

  4. Miles says:

    Good spot Dmitry, the missing ’static’ from Y.getInstance() is a typo in this example (now fixed), but I guess the case I was working on didn’t declare the constant as final, hence causing the bug.

  5. hasan says:

    For me the code works fine, no runtime exceptions. i have added some System.out. in X() constructor, X.doSomething() and Y.getInstance().

    and the output i got in this order:

    Inside X constructor:blah
    Inside getInstance():test.bugs.Y@923e30
    Inside doSomething:4

Leave a Reply

Line and paragraph breaks automatic.
XHTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>