Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static block not executed without initialization

I have a question regarding static blocks:

Let's say i've got a class looking like this:

class SomeClass {
    static {
        System.out.println("static block");
    }
}

and I define a variable of type SomeClass somewhere.

public static void main(String args[]) {
    SomeClass foo;
}

Now i thought the static block would have been executed but it wasn't. As far as i know the static block is executed as soon as the classloader loads the SomeClass class. Now to my real question:

Isn't the class loaded as soon as I define a variable of that type?. If yes why isn't the static block executed?

If the answer should be no, then how can i know if a class has already been loaded by the class loader and what are the different possibilities to have the class loaded (I know of 2: initializing the variable & using a static field/method)

like image 324
ParkerHalo Avatar asked Nov 19 '15 13:11

ParkerHalo


2 Answers

Refer to this doc: http://www.javaworld.com/article/2077260/learn-java/learn-java-the-basics-of-java-class-loaders.html

So when are classes loaded? There are exactly two cases: when the new bytecode is executed (for example, FooClass f = new FooClass();) and when the bytecodes make a static reference to a class (for example, System.out).

In your example, SomeClass foo; does neither execute the bytecode of SomeClass nor make a static reference to SomeClass. That's why the class is not loaded.

So following your example, add a static field in the class

public class SomeClass {
    static {
        System.out.println("static block");
    }

    static String abc = "abc";
}

SomeClass is loaded in either:

SomeClass foo = new SomeClass();

Or

System.out.println(SomeClass.abc);
like image 70
Bon Avatar answered Nov 04 '22 02:11

Bon


Isn't the class loaded as soon as I define a variable of that type?.

Yes, it is loaded1, but it won't be initialized as a result of declaring a variable. However, when you create an instance of that type, or access a static field of that type, that is sufficient to trigger initialization, including the execution of static blocks.

See this related Q&A - When does static class initialization happen? - which lists all of the things that can trigger initialization.


How can i know if a class has already been loaded by the class loader and what are the different possibilities to have the class loaded (I know of 2: initializing the variable & using a static field/method)

The only ways I can think of for finding out when a class is loaded (as distinct from initialized) are:

  • turning on the JVM's class loader messages (using -verbose:class), or

  • using a customer classloader that notices, and does something appropriate when it sees a request to load the class.

A class is actually going to be loaded:

  • when it is explicitly loaded using Class.forName or similar, or a direct call to a classloader,

  • when it is necessary to load it in order to link another class, or

  • at JVM launch time, if the class is named as the entry point class.

The loading / linking / initializing steps are specified in Chapter 12 of the JLS.


1 - In fact, SomeClass needs to be loaded at the same time that the class containing that main method is linked; i.e. before the method containing that local declaration is called.

like image 28
Stephen C Avatar answered Nov 04 '22 03:11

Stephen C