Why does .class not invoke the static block in a Class?

JavaClassStaticInitialization

Java Problem Overview


This is the code I have:

public class StupidClass {
    static {
        System.out.println("Stupid class loaded!");
    }
}

And the tests I have, which I run separately.

import org.junit.Test;

public class StupidTest {
    @Test
    public void foo() throws ClassNotFoundException {
        final Class<?> stupidClass = Class.forName("StupidClass");
        System.out.println(stupidClass.getSimpleName());
    }

    @Test
    public void bar() throws ClassNotFoundException {
        final Class<StupidClass> stupidClassClass = StupidClass.class;
        System.out.println(stupidClassClass.getSimpleName());
    }
}

When I run test foo I will see:

Stupid class loaded!
StupidClass

But when I run the test bar all I see is:

StupidClass

Quoting from this page..

> Class objects are constructed automatically by the Java Virtual > Machine as classes are loaded and by calls to the defineClass method > in the class loader.

So my understanding is, in test bar, Stupid class is loaded, otherwise I would have seen a null I guess? So Class object is created because class itself is loaded..

And now quoting from this page

> Static initialization blocks are run when the JVM (class loader - to > be specific) loads StaticClass (which occurs the first time it is > referenced in code).

So I am expecting to see the "Stupid class loaded!" text in test bar as well, but I am not.

Also quoting from Thinking in Java

> Each of the classes Candy, Gum, and Cookie has a static clause that is > executed as the class is loaded for the first time.

which is not very accurate it seems..

What am I missing?

Java Solutions


Solution 1 - Java

> Static initialization blocks are run when the JVM (class loader - to be specific) loads StaticClass (which occurs the first time it is referenced in code).

The above quote is plain wrong, but it is just one instance of a very widespread misconception.

  1. Class is not initialized when it's being loaded, but when a static class member is first referenced. This is precisely governed by the specification.

  2. Class loading does not occur when the class is first referenced, but at an implementation-dependent point.

  3. The last moment when the class must be loaded is when the class is referenced, which is not the same as referencing a class member.

Class.forName initializes the class by default, but you have the choice of calling an overload that takes a boolean initialize and supplying false. You'll get the class loaded without initializing.

Solution 2 - Java

Class Loading and initialization are 2 different things. A class can be loaded but not initialized until it is really necessary. Static initializers are run only when a class is being initialized <> NOT loaded, "initialized"

In the first case you are loading and initializing a class when you use class.forName(), that's why the static initializers are run and hence you see "Stupid class loaded!" as output . In the second case, you are just assigning a reference of the class, the class is loaded (use java -verbose:class to see what classes are loaded) but you aren't really initializing it (or to be more precise, not doing anything that forces the initializers to run). Thus you don't see the output as Stupid class loaded!. Try doing something like calling newInstance() on the class, it should force the initialization of the class and you should see Stupid class loaded!

My code :

public class CheckPalindrome {

	public static void main(String[] args) {
		Class<Test> t = Test.class;
	}

}
// class being loaded
class Test {
	static {
		System.out.println("aaa");
	}
}

Classes that are loaded

...
[Loaded Test from file:/Workspaces/SampleTest/Java8/bin/]
...

^ - This shows that the class is loaded but not initialized.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKoray TugayView Question on Stackoverflow
Solution 1 - JavaMarko TopolnikView Answer on Stackoverflow
Solution 2 - JavaTheLostMindView Answer on Stackoverflow