Core Javamedium

Static Initializers

Static initializer blocks (static { ... }) run once when a class is loaded by the JVM, before any instances are created or static methods called. They initialize static fields that require complex logic.

Memory anchor

Static initializer = the 'grand opening' ribbon-cutting for a store. Happens exactly once, before any customer enters. If the ribbon-cutting catches fire, the store is permanently condemned.

Expected depth

Class initialization is triggered by: creating an instance, calling a static method, reading/writing a static field, or reflection. The JVM guarantees class initialization is thread-safe — only one thread performs it; others block. Static initializers run in textual order. If a static initializer throws an unchecked exception, the class enters a failed initialization state and subsequent attempts to use it throw ExceptionInInitializerError wrapping the original.

Deep — senior internals

The initialization-on-demand holder idiom exploits JVM class initialization guarantees to implement lazy, thread-safe singletons without synchronization: a nested private static class holds the singleton instance in a static final field; the outer class triggers the inner class's initialization only when getInstance() is first called. Circular class initialization (A's static initializer triggers loading of B which triggers loading of A) can cause partially initialized classes to be visible, leading to NullPointerExceptions on static fields that haven't been set yet.

🎤Interview-ready answer

Static initializer blocks run once at class initialization time and are guaranteed by the JVM to be executed by exactly one thread (others block), making them thread-safe. A static initializer that throws will put the class in a permanently failed state — ExceptionInInitializerError is thrown on first access and NoClassDefFoundError on all subsequent accesses. The initialization-on-demand holder pattern exploits this guarantee for zero-overhead lazy singleton initialization.

Common trap

If a static initializer throws a RuntimeException, the class can never be initialized again in that JVM run — subsequent attempts throw NoClassDefFoundError, not the original exception, making debugging confusing.