Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Because Java is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface; for example, a variable initializer in class A might invoke a method of an unrelated class B, which might in turn invoke a method of class A. The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure. It assumes that the Class object has already been verified and prepared, and that the Class object contains state that indicates one of four situations:
- This
Classobject is verified and prepared but not initialized. - This
Classobject is being initialized by some particular thread T. - This
Classobject is fully initialized and ready for use. - This
Classobject is in an erroneous state, perhaps because the verification or preparation step failed, or because initialization was attempted and failed.
The procedure for initializing a class or interface is then as follows:
- Synchronize (§14.17) on the
Classobject that represents the class or interface to be initialized. This involves waiting until the current thread can obtain the lock for that object (§17.13). - If initialization is in progress for the class or interface by some other thread, then
wait(§20.1.6) on thisClassobject (which temporarily releases the lock). When the current thread awakens from thewait, repeat this step. - If initialization is in progress for the class or interface by the current thread, then this must be a recursive request for initialization. Release the lock on the
Classobject and complete normally. - If the class or interface has already been initialized, then no further action is required. Release the lock on the
Classobject and complete normally. - If the
Classobject is in an erroneous state, then initialization is not possible. Release the lock on theClassobject and throw aNoClassDefFoundError. - Otherwise, record the fact that initialization of the
Classobject is now in progress by the current thread and release the lock on theClassobject. - Next, if the
Classobject represents a class rather than an interface, and the superclass of this class has not yet been initialized, then recursively perform this entire procedure for the superclass. If necessary, verify and prepare the superclass first. If the initialization of the superclass completes abruptly because of a thrown exception, then lock thisClassobject, label it erroneous, notify all waiting threads (§20.1.10), release the lock, and complete abruptly, throwing the same exception that resulted from initializing the superclass. - Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block, except that
finalclass variables and fields of interfaces whose values are compile-time constants are initialized first (§8.3.2.1, §9.3.1, §13.4.8). - If the execution of the initializers completes normally, then lock this
Classobject, label it fully initialized, notify all waiting threads (§20.1.10), release the lock, and complete this procedure normally. - Otherwise, the initializers must have completed abruptly by throwing some exception E. If the class of E is not
Erroror one of its subclasses, then create a new instance of the classExceptionInInitializerError, with E as the argument, and use this object in place of E in the following step. But if a new instance ofExceptionInInitializerErrorcannot be created because anOutOfMemoryErroroccurs, then instead use anOutOfMemoryErrorobject in place of E in the following step. - Lock the
Classobject, label it erroneous, notify all waiting threads (§20.1.10), release the lock, and complete this procedure abruptly with reason E or its replacement as determined in the previous step.
(Due to a flaw in some early implementations of Java, a exception during class initialization was ignored, rather than causing an ExceptionInInitializerError as described here.)