Search code examples
javavariablesfinallyinitialization

Java uninitialized variable with finally curiosity


I was trying to come up with obscure test cases for an alternative open-source JVM I am helping with (Avian) when I came across an interesting bit of code, and I was surprised that it didn't compile:

public class Test {
    public static int test1() {
        int a;
        try {
            a = 1;
            return a; // this is fine
        } finally {
            return a; // uninitialized value error here
        }
    }
    public static void main(String[] args) {
        int a = test1();
    }
}

The most obvious code path (the only one that I see) is to execute a = 1, "attempt" to return a (the first time), then execute the finally, which actually returns a. However, javac complains that "a" might not have been initialized:

    Test.java:8: variable a might not have been initialized  
        return a;  
               ^  

The only thing I can think of that might cause / allow a different code path is if an obscure runtime exception were to occur after the start of the try but before the value 1 is assigned to a - something akin to an OutOfMemoryError or a StackOverflowException, but I can't think of any case where these could possibly occur at this place in the code.

Can anyone more familiar with the specifics of the Java standard shed some light on this? Is this just a case where the compiler is being conservative - and therefore refusing to compile what would otherwise be valid code - or is something stranger going on here?


Solution

  • It may seem counter intuitive that an exception could occur on the a=1 line, but a JVM error could occur. Thus, leaving the variable a uninitialized. So, the compiler error makes complete sense. This is that obscure runtime error that you mentioned. However, I would argue that an OutOfMemoryError is far from obscure and should be at least thought about by developers. Furthermore, remember that the state that sets up the OutOfMemoryError could happen in another thread and the one action that pushes the amount of heap memory used past the limit is the assignment of the variable a.

    Anyways, since you are looking at compiler design, I'm also assuming that you already know how silly it is to return values in a finally block.