Understanding Java Class Initialization: Key Scenarios and Examples

Java class initialization can be a complex topic, but understanding when and how classes are initialized is crucial for mastering Java. According to the Java Virtual Machine Specification (Chapter 5.5 Initialization)1, there are exactly six scenarios where a class must be initialized immediately: Situations That Trigger Class Initialization: Encountering bytecode instructions such as: new (creating an instance) getstatic (reading a static field not modified by final) putstatic (setting a static field not modified by final) invokestatic (calling a static method) Using reflection methods from the java.lang.reflect package. If the parent class has not been initialized. When the JVM starts and a main class is specified for execution. Using Java 7+ dynamic language support when a MethodHandle resolves to: REF_getStatic REF_putStatic REF_invokeStatic REF_newInvokeSpecial An interface defines a default method, and the implementation class of the interface is initialized simultaneously. Class Initialization Scenarios with Examples 1. Subclass References Parent Class Referencing a static field of a superclass through a subclass does not initialize the subclass: class Super { static { System.out.println("Super"); } public static int value = 1; } class Sub extends Super { static { System.out.println("Sub"); } } public class Main { public static void main(String[] args) { System.out.println(Sub.value); } } Output: Super 1 Explanation: Only the superclass is initialized because the static field belongs to it. Accessing Sub.value only triggers the initialization of Super. 2. Array Reference Does Not Trigger Initialization Creating an array of a class does not initialize the class itself: public class Main { public static void main(String[] args) { Sub[] array = new Sub[5]; } } Output: No output, indicating that the Sub class is not initialized. Explanation: An array reference does not trigger class initialization. The JVM creates a class named "[Lcom.example.demo.Sub" to represent the one-dimensional array but does not initialize the Sub class itself. 3. Constant Pool Reference If a constant is defined as final, it is stored directly in the constant pool of the calling class during compilation, avoiding initialization: class Super { static { System.out.println("Super"); } public static final String HELLO = "Hello"; } public class Main { public static void main(String[] args) { System.out.println(Super.HELLO); } } Output: Hello Explanation: Since the constant is stored directly in the calling class's constant pool, the Super class does not get initialized. 4. Interface Initialization Rules Unlike classes, interfaces do not initialize all parent interfaces at once. Instead, they are initialized only when actually used. Also, interfaces cannot contain static blocks, but they do have a method to initialize variables. Conclusion Understanding these specific scenarios helps in controlling when classes are initialized, which is especially useful for optimizing application startup time and avoiding unexpected behavior in Java applications. Reference Yellin, F. and Lindholm, T., 1996. The java virtual machine specification. ↩

May 11, 2025 - 15:36
 0
Understanding Java Class Initialization: Key Scenarios and Examples

Java class initialization can be a complex topic, but understanding when and how classes are initialized is crucial for mastering Java. According to the Java Virtual Machine Specification (Chapter 5.5 Initialization)1, there are exactly six scenarios where a class must be initialized immediately:

Situations That Trigger Class Initialization:

  1. Encountering bytecode instructions such as:

    • new (creating an instance)
    • getstatic (reading a static field not modified by final)
    • putstatic (setting a static field not modified by final)
    • invokestatic (calling a static method)
  2. Using reflection methods from the java.lang.reflect package.

  3. If the parent class has not been initialized.

  4. When the JVM starts and a main class is specified for execution.

    1. Using Java 7+ dynamic language support when a MethodHandle resolves to:
    2. REF_getStatic
    3. REF_putStatic
    4. REF_invokeStatic
    5. REF_newInvokeSpecial
  5. An interface defines a default method, and the implementation class of the interface is initialized simultaneously.

Class Initialization Scenarios with Examples

1. Subclass References Parent Class

Referencing a static field of a superclass through a subclass does not initialize the subclass:

class Super {
    static { System.out.println("Super"); }
    public static int value = 1;
}

class Sub extends Super {
    static { System.out.println("Sub"); }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Sub.value);
    }
}

Output:

Super
1

Explanation:
Only the superclass is initialized because the static field belongs to it. Accessing Sub.value only triggers the initialization of Super.

2. Array Reference Does Not Trigger Initialization

Creating an array of a class does not initialize the class itself:

public class Main {
    public static void main(String[] args) {
        Sub[] array = new Sub[5];
    }
}

Output:

No output, indicating that the Sub class is not initialized.

Explanation:
An array reference does not trigger class initialization. The JVM creates a class named "[Lcom.example.demo.Sub" to represent the one-dimensional array but does not initialize the Sub class itself.

3. Constant Pool Reference

If a constant is defined as final, it is stored directly in the constant pool of the calling class during compilation, avoiding initialization:

class Super {
    static { System.out.println("Super"); }
    public static final String HELLO = "Hello";
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Super.HELLO);
    }
}

Output:

Hello

Explanation:
Since the constant is stored directly in the calling class's constant pool, the Super class does not get initialized.

4. Interface Initialization Rules

Unlike classes, interfaces do not initialize all parent interfaces at once. Instead, they are initialized only when actually used. Also, interfaces cannot contain static blocks, but they do have a method to initialize variables.

Conclusion

Understanding these specific scenarios helps in controlling when classes are initialized, which is especially useful for optimizing application startup time and avoiding unexpected behavior in Java applications.

Reference

  1. Yellin, F. and Lindholm, T., 1996. The java virtual machine specification. ↩