Wednesday, June 15, 2011

Will class literals (some-named-type.class) cause class initialization?

Suppose you have the following classes:

class Foo {
    static int cls_var = 10;
    static {
        System.out.println("cls_var:" + cls_var);
    }
   
    int inst_var = 20;
}

class Bar {
    public static void main(String arg[]) {
        System.out.println(Foo.class.getName());
    }
}


Will the class literal in bold blue cause Foo to be initialized (assign cls_var to 10 and run the following initializer)?
On the console you will only see "Foo"; you will not see "cls_var:10" as you may think you should see.

In order to find why, you need to know that JVM subject a class to the following 3 processes in order:

  1. Loading 
  2. Linking: Verification, Preparation, and Resolution   
  3. Initialization
The class literal evaluates to the Class object for the named type (or for void) as defined by the defining class loader of the class of the current instance, and this information is accommodated by the above Step 1.

Foo's static variable initialization and the executor of static initializer are done in Step 3. Step 3 can be lazily executed by JVM after Step 1, which means Step 3 may not immediately follow Step 1.

This is why you will only see "Foo" output on the console. For more details, please see the linked JVM spec and Java language spec.