16

As per JLS:

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

T is a class and an instance of T is created.

Also it says,

Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class

I infer two points from this

  • Class initialization consists of executing its static initializers
  • Class initialization happens if a class is instantiated.

Now,

I assume when I create an object of a class Test in its own (Test's own) static initializer it should throw me a stack overflow as it should call itself repeatedly because as per the above two points, instantiation of the class should initialize the class and initialization block has the instantiation of the class. A stack overflow occurs when I instantiate the class in its own constructor or in its own instance initializers.

For example,

public class Test {

    static{
        System.out.println("static test");
        new Test();
    }
    {
       //new Test(); // This will give a stack overflow
        System.out.println("intializer");
    }

    public Test(){
        //new Test(); // This will give a stack overflow
        System.out.println("constructor");
    }
    public static void main(String[] args) {
    }

}

However the result is something different.

Result:

static test intializer constructor

Either I am too confused understanding the initialization of the class or I do apologize if I am missing something very obvious here and appreciate your help.

5
  • 2
    static block is only called once .. why do you think it will be called many times? Commented Jul 20, 2015 at 2:19
  • @Constantin Because the JLS says so. (Or more accurately, it implies that in this case the static initializer must run before the static initializer runs) Commented Jul 20, 2015 at 2:24
  • Constantin, thanks for the response, i was thinking that static block is in turn creating the object of class itself which would initialize the class again(duh on me if that is blooper however i am confused here) , anyway i believe static block is only called once and that block is instantiating the class itself which is nothing but a singleton object? Commented Jul 20, 2015 at 2:25
  • Also: Is this a "why does this happen in practice?" type question or a language-lawyer type question? ("is this supposed to happen?") Commented Jul 20, 2015 at 2:25
  • There is a difference between initialization of an instance and the initialization of a class in the classloader. .. And how did you know I was a lawyer?. Commented Jul 20, 2015 at 2:29

2 Answers 2

15

Step 3 of the class initialization procedure, specified in JLS section 12.4.2, is

If the Class object for C indicates that initialization is in progress for C by the current thread, then this must be a recursive request for initialization. Release LC and complete normally.

Creating an instance of a class in its static initializer doesn't recursively reinitialize the class; recursive requests for initialization are detected and don't do anything.

(Note that "complete normally" means "the operation is done", not "follow the steps that would normally be followed to complete the operation"; it's opposite to "complete abruptly", which would mean we got some kind of exception or error.)

Sign up to request clarification or add additional context in comments.

6 Comments

Release LC and completes normally .. how ? I mean since it is recursive call current thread is trying to initialize the class where the class static code requests initialization how it will end smoothly ? can you explain little bit more if possible
@Babel: "Complete normally" is a technical term defined elsewhere. It basically means we're done; it doesn't imply we have to do something else to finish up.
Not to do anything is easy to understand, and at this time, the class is not completely initialized, but it allows to access its static fields and methods, right? But why need to release LC? the current thread is initializing the class and receive recursive initialization request, it knows no other thread is requesting, releasing LC make no sense.
@Richard: Why would we keep holding LC? We don't need to hold it for the entire duration of the initialization; it's only necessary for a short period at the start and end of an initialization. Particularly, I don't see any requirement that the initialization lock be reentrant, so releasing the lock prevents deadlock on recursive initialization requests.
@user2357112 If LC is not held for the duration of the initialization, what on earth does the lock protect? the status of the initialization?
|
2

The static initializer only gets called when the class is loaded. Instantiating an object in the static initializer isn't going to result in the class getting loaded again, classloading of a class only happens once, the classloader caches the class for the life of the JVM instance.

If you created a new instance in the instance initializer or in the constructor then you'd get the stackoverflow error.

1 Comment

thanks for the response , main execution thread is loading the test class via classloader only once and the object in the static initializer is singleton

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.