javamemoryjvmclassloadingin-class-initialization

Class Loading vs Initialisation: Java static final variable


Example.java

public class Example {

    static final int i = 10;
    static int j = 20;
    static {
        System.out.println("Example class loaded and initialized");
    }
}

Use.java

import java.util.Scanner;
public class Use {
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int ch = 1;
        while(ch != 0) {
            System.out.print("Enter choice: ");
            ch = sc.nextInt();

            if (ch == 1) {
                System.out.println("Example's i = " + Example.i);
            } else if(ch == 2){
                System.out.println("Example's j = " + Example.j);
            }
        }
    }
}

When I run with java -verbose:class Use, and give input as 1 then output is 10 i.e the constant i value. But Example class is not loaded yet. However, when I give input as 2, only then Example class is loaded into the JVM, as visible by the verbose output, and then static block inside Example is executed and also j's value initialized and then printed.

My Query is: If for the input 1 i.e when the static final (constant) value of a class Example is requested in another class Use, then from where is that constant value fetched if the class Example was never loaded into the JVM till then? When and how was the static final i intialized and store into the JVM memory?


Solution

  • According to the Java language specification section 12.4.1 (emphasis added):

    A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

    • T is a class and an instance of T is created.

    • A static method declared by T is invoked.

    • A static field declared by T is assigned.

    • A static field declared by T is used and the field is not a constant variable (§4.12.4).

    A constant variable is a final variable that is initialized with a constant expression. In your code, Example.i is a constant variable, and therefore does not cause the class to be loaded.

    So if the class is not loaded, where does the value com from?

    The language specification requires the compiler to inline its value. From section of binary compatibility 13.1:

    1. A reference to a field that is a constant variable (§4.12.4) must be resolved at compile time to the value V denoted by the constant variable's initializer.

      If such a field is static, then no reference to the field should be present in the code in a binary file, including the class or interface which declared the field. Such a field must always appear to have been initialized (§12.4.2); the default initial value for the field (if different than V) must never be observed.