Fundamentals 13 min read

Why Accessing a Superclass Static Field Skips Subclass Initialization – JVM Class Loading Explained

This article examines common Java interview questions about static field access, demonstrates how the JVM loads and initializes classes, explains why a subclass may not be initialized when referencing a superclass static variable, and details each phase of the JVM class‑loading lifecycle.

Senior Brother's Insights
Senior Brother's Insights
Senior Brother's Insights
Why Accessing a Superclass Static Field Skips Subclass Initialization – JVM Class Loading Explained

The article starts with two typical Java interview questions that test understanding of the JVM class‑loading mechanism, especially the behavior of static fields.

Interview Question 1 – Accessing a Non‑final Static Field

public class SuperClass {
    static {
        System.out.println("SuperClass static init");
    }
    public static String ABC = "abc";
}

public class SubClass extends SuperClass {
    static {
        System.out.println("SubClass static init");
    }
}

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

Running the program prints:

SuperClass static init
abc

The output shows that only SuperClass is initialized. The JVM initializes the class that actually defines the referenced static field; accessing SubClass.ABC triggers initialization of SuperClass but not SubClass because the field belongs to the superclass.

Interview Question 2 – Adding final to the Static Field

public class SuperClass {
    static {
        System.out.println("SuperClass static init");
    }
    public static final String ABC = "abc";
}

public class SubClass extends SuperClass {
    static {
        System.out.println("SubClass static init");
    }
}

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

The program now prints only:

abc

Because the field is final, the compiler treats it as a constant and inlines its value into the calling class. The reference no longer requires loading SuperClass, so the static initializer is never executed.

JVM Class‑Loading Process

The JVM loads class data from a .class file (or other sources), verifies it, prepares it, resolves symbolic references, initializes it, uses it, and eventually unloads it. Loading, verification, preparation, and initialization occur before the class can be used; resolution may be deferred until after initialization to support dynamic binding.

Class loading lifecycle diagram
Class loading lifecycle diagram

Loading Phase

Obtain the binary byte stream of the class using its fully‑qualified name (from a .class file, JAR, network, etc.).

Convert the byte stream into the runtime data structures stored in the method area.

Create a java.lang.Class object that serves as the entry point for accessing the class’s metadata.

Verification Phase

The JVM checks that the class file conforms to the specification and does not threaten VM security. Verification includes:

File‑format verification (magic number, version, constant‑pool validity).

Metadata verification (semantic checks such as correct inheritance, method signatures, and access flags).

Bytecode verification (data‑flow and control‑flow analysis to ensure type safety and proper instruction usage).

Symbolic reference verification (ensuring that constant‑pool symbolic references can be resolved).

Preparation Phase

During preparation the JVM allocates memory for static variables in the method area and assigns them default values. For example:

public static String ABC = "abc";

If the variable is declared final, the constant value is stored directly during this phase.

Resolution Phase

Resolution replaces symbolic references in the constant pool with direct references. When the JVM resolves a field reference such as SubClass.ABC, it first looks for the field in SubClass; if not found, it recursively searches superclasses and interfaces. Failure results in java.lang.NoSuchFieldError or java.lang.IllegalAccessError.

Initialization Phase

Initialization executes the class’s <clinit>() method, which consists of all static variable initializations and static blocks, ordered as they appear in the source file. The parent class’s <clinit>() runs before the child’s. The JVM guarantees that only one thread executes <clinit>() for a given class, blocking other threads until completion.

VM Specification – When Initialization Occurs (JDK 1.7)

Execution of new, getstatic, putstatic, or invokestatic on a class that has not yet been initialized.

Reflective operations via java.lang.reflect that access a class.

When initializing a class, if its superclass has not been initialized, the superclass is initialized first.

The main class specified for program start is initialized first.

Dynamic language support (method handles) that resolve to static fields or methods of an uninitialized class.

Conclusion

Understanding these steps clarifies why static field access can trigger or bypass class initialization and prepares readers for deeper topics such as class loaders and the parent‑delegation model.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaJVMInitializationclass loadingStatic FieldsBytecode Verification
Senior Brother's Insights
Written by

Senior Brother's Insights

A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.