8

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)

9
  • 4
    The compiler could remove foo, the import of SomeClass in this case. Class.forName("... SomeClass") does initialize the class. Commented Nov 19, 2015 at 13:26
  • @JoopEggen ah ok, but couldn't the compiler also remove foo when it was initialized but never used? Or will the compiler never do that? Commented Nov 19, 2015 at 13:27
  • 2
    It is a common optimization for the compiler (and runtime) to delay loading classes until they are needed. import statements are directives to the compiler, but are not executed at run time. I have seen environments where a class is loaded only when a method that references the class is executed but not when other methods that don't reference the class are executed. Commented Nov 19, 2015 at 13:28
  • 1
    Class.forName is overloaded with a boolean parameter to initialize the class; per default true. Initializing the variable probably suffices to invoke class loading and initialization, even if the entire object is optimized away. One should consider that (ideally) there are more than one java compilers. Commented Nov 19, 2015 at 13:42
  • 1
    @ParkerHalo Yes. A naive compiler would not remove the unused variable. Commented Nov 19, 2015 at 16:53

2 Answers 2

5

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);
Sign up to request clarification or add additional context in comments.

1 Comment

Ermm .... the SomeClass class is >>loaded<<, but it isn't >>initialized<<, and class initialization is when the static blocks get executed.
4

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.