This is somewhat related to static variable initialization order, but this question doesn't really answer my question.
When I run the following code, I expect undefined behavior or something with infinite recursion to happen:
class A {
static File test = B.test;
public static void main(String[] args) {
System.out.println(A.test);
System.out.println(B.test);
}
}
class B {
static File test = A.test;
}
However, instead I see:
null
null
Why does this happen?
The answer comes from JLS section 12.4. We start with 12.4.1:
12.4.1. When Initialization Occurs
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.
A static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
When A.main is invoked, the third clause applies, and thus class A (and by extension A.test) must be initialized. The initialization of A.test triggers the fourth clause above, meaning that B must now be initialized. B must now access fields of A, but A has not yet initialized.
We need to now dig into section 12.4.2:
12.4.2. Detailed Initialization Procedure
...
For each class or interface C, there is a unique initialization lock LC. The mapping from C to LC is left to the discretion of the Java Virtual Machine implementation. The procedure for initializing C is then as follows:
Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC.
If the Class object for C indicates that initialization is in progress for C by some other thread, then release LC and block the current thread until informed that the in-progress initialization has completed, at which time repeat this step.
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.
Step 3 is the one we take here. Class A is already undergoing initialization by the current thread, so we are in a recursive initialization situation. We thus just give up and complete normally right away, so A.test remains null and B.test gets the value of A.test which is null.
Related
When we say java Test, class loaders will load .class files into method area and static variables if any are initialized to corresponding values assigned and static blocks will be executed.
In java execution means code has to be interpreted by java interpreter. But how static block executes here without interpretation? It is still in a class loading phase, isn’t it?
But in most of the blogs and videos they say once after class loading completes, new thread will be created and it will look for main method and starts executing it. Interpreter comes to picture once main method starts execution in all blogs I saw.
class Test {
static int x = 10;
static {
int y = 10;
System.out.println(x);
}
public static void main(String[] args) {
}
}
The existence of an interpreter is an implementation detail that is irrelevant for describing the behavior of a program. In principle, it is possible to have a JVM without an interpreter at all, as it could have only a compiler that translates all byte code to native code before executing, and still implement the correct behavior. Current desktop and server JVMs have both, executing the code in a mixed mode.
So, it is also irrelevant at which point blogs and videos mention the existence of an interpreter as a way to execute the code, the execution of code always implies the existence of technical means to execute the code, like an interpreter or compiler.
The actual behavior has been specified in The Java Language Specification, §12.4.1:
§12.4.1. When Initialization Occurs
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.
A static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6) and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.¹
When a class is initialized, its superclasses are initialized (if they have not been previously initialized), as well as any superinterfaces (§8.1.5) that declare any default methods (§9.4.3) (if they have not been previously initialized). Initialization of an interface does not, of itself, cause initialization of any of its superinterfaces.
¹ this last bullet has been removed from newer specifications
Since the invocation of the main method is an invocation of “a static method declared by” your class, it implies the initialization of that class before the invocation. As you can derive from the last section, if the class containing the main method has uninitialized superclasses, they are initialized even before that class.
For the standard Java launcher, the order of events is
The main thread is created
The main thread loads the specified application class
The super classes of the application class are initialized, if not already initialized
The application class is initialized
The method static void main(String[]) is invoked on the application class
The terms “application class” and “main class” are interchangeable.
Note that this list is only meant to bring these events into the right order. There are far more events happening behind the scenes. Obviously, for asking the application class loader to load the application class, given by name, the classes String, Class, and ClassLoader must have been loaded and initialized, which also implies that their super class, Object has been initialized even before that. The existence of the main thread implies the loading and initialization of the class Thread. And all these classes use other classes behind the scenes.
You may run your application with the -verbose:class option to see which classes are already loaded before your application class.
I have a case like
MyClass.invoke( anObject.setSystem() );
Is there a guarantee that anObject.setSystem() will be called before MyClass is loaded? As the initialization code of MyClass depends on the result of anObject.setSystem().
It is running with Java 8. Any suggestions/hints would be appreciated. Many thanks
MyClass will be loaded and all of its static fields and static initializers will be initialized before MyClass.invoke() is called.
See JLS 12.14.1
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.
T is a class and a static method declared by T is invoked. <------------ right here
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
EDIT
Thanks to #Holger and #gigi's comments, there was still the question as to whether the invocation that triggers the loading of the class occurs before or after the evaluation of the argument expression passed into it. I think the answer to that is in JLS 15.12.4, which states,
At run time, method invocation requires five steps. First, a target reference may be computed. Second, the argument expressions are evaluated. Third, the accessibility of the method to be invoked is checked. Fourth, the actual code for the method to be executed is located. Fifth, a new activation frame is created, synchronization is performed if necessary, and control is transferred to the method code.
The evaluation of argument expressions (step 2) occurs before the code to execute the method is located, (step 4, which probably results in the class being loaded and statically initialized) and only then, in the final step, is the static method invoked.
I dont know whether this question has been asked before or not .I searched but couldn't find any duplicate question. If you find any related question please mention the link.
public class Exp
{
Exp()
{
System.out.println("Hello"); //3
}
{ System.out.println("Hello")}; //1
{ static{System.out.print("x");} //2
}
The order of printing of messages is 2,1,3.
What are the significance of these lines 1 & 2 and why that exec order
Line "1" is an instance initializer, which runs when an object is first created, before any constructors are called.
Line "2" is a static initializer, which runs when a class is first loaded, before any objects are created.
Section 12.5 of the JLS specifies when instance initializers are run:
Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:
Assign the arguments for the constructor to newly created parameter
variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation
(§8.8.7.1) of another constructor in the same class (using this), then
evaluate the arguments and process that constructor invocation
recursively using these same five steps. If that constructor
invocation completes abruptly, then this procedure completes abruptly
for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor
invocation of another constructor in the same class (using this). If
this constructor is for a class other than Object, then this
constructor will begin with an explicit or implicit invocation of a
superclass constructor (using super). Evaluate the arguments and
process that superclass constructor invocation recursively using these
same five steps. If that constructor invocation completes abruptly,
then this procedure completes abruptly for the same reason. Otherwise,
continue with step 4.
Execute the instance initializers and instance variable initializers
for this class, assigning the values of instance variable initializers
to the corresponding instance variables, in the left-to-right order in
which they appear textually in the source code for the class. If
execution of any of these initializers results in an exception, then
no further initializers are processed and this procedure completes
abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution
completes abruptly, then this procedure completes abruptly for the
same reason. Otherwise, this procedure completes normally.
(emphasis mine)
The rest of the body of the constructor is executed after the instance initializer.
static blocks of a class are executed during class loading along with constants (static final members). 3 is invoked when the object is instantiated.
For you to understand better debug the code through your IDE to understand the sequence of execution.
See http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. Here is an example:
static {
// whatever code is needed for initialization goes here
}
A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
The reason for the execution order is, in non-static block you might want to use static members, but in static block you cannot use non-static members. So it makes sense to execute static block first.
non-static block allows you to abstract the code that every constructor needs to execute, therefore it gets executed before constructor.
More detailed order of execution:
1.static block of superclass
2.static block of this class
3.non-static block of superclass
4.constructor of superclass
5.non-static block of this class
6.constructor of this class
This question already has answers here:
In what order do static/instance initializer blocks in Java run?
(8 answers)
Closed 9 years ago.
I'm trying to discover the order in which initialization occurs, or rather the reason behind why initialization occurs in this order. Given the code:
public class Main {
{
System.out.printf("NON-STATIC BLOCK\n");
}
static{
System.out.printf("STATIC BLOCK\n");
}
public static Main m = new Main();
public Main(){
System.out.printf("MAIN CONSTRUCTOR\n");
}
public static void main(String... args) {
//Main m = new Main();
System.out.printf("MAIN METHOD\n");
}
}
Output:
STATIC BLOCK
NON-STATIC BLOCK
MAIN CONSTRUCTOR
MAIN METHOD
However, moving m's declaration before the initialization block produces:
NON-STATIC BLOCK
MAIN CONSTRUCTOR
STATIC BLOCK
MAIN METHOD
and I have absolutely no idea why it occurs in this order. Furthermore, if I eliminate the static keyword in the declaration of m, neither the init block nor the constructor fire. Can anyone help me out with this?
I think you're just missing section 12.4.2 of the JLS, which includes:
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.
The "in textual order" part is the important bit.
If you change m from being static variable to an instance variable, then the field won't be initialized by class initialization - it'll only be initialized by instance initialization (i.e. when an instance is constructed). At the moment, that'll cause a stack overflow - creating one instance requires creating another instance, which requires creating another instance, etc.
EDIT: Similarly section 12.5 specifies instance initialization, including these steps:
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
So that's why you're seeing "NON-STATIC BLOCK" before "MAIN CONSTRUCTOR".
In my application, there is a class like below:
public class Client {
public synchronized static print() {
System.out.println("hello");
}
static {
doSomething(); // which will take some time to complete
}
}
This class will be used in a multi thread environment, many threads may call the Client.print() method simultaneously. I wonder if there is any chance that thread-1 triggers the class initialization, and before the class initialization complete, thread-2 enters into print method and print out the "hello" string?
I see this behavior in a production system (64 bit JVM + Windows 2008R2), however, I cannot reproduce this behavior with a simple program in any environments.
In Java language spec, section 12.4.1 (http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html), it says:
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.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the reference to the field is not a compile-time constant (§15.28). References to compile-time constants must be resolved at compile time to a copy of the compile-time constant value, so uses of such a field never cause initialization.
According to this paragraph, the class initialization will take place before the invocation of the static method, however, it is not clear if the class initialization need to be completed before the invocation of the static method. JVM should mandate the completion of class initialization before entering its static method according to my intuition, and some of my experiment supports my guess. However, I did see the opposite behavior in another environment. Can someone shed me some light on this?
Any help is appreciated, thanks.
My understanding of the quoted text is that the class initialization process is completed (will be initialized) before a static method declared by T is invoked.
will be initialized implies that the initialization process has been started and has terminated.
So it shouldn't be possible (to my understanding) that, while the static initializer is executed because Thread A called print, another Thread already can call print.
Chapter 12.4.2 of the JLS describes the detailed initialization procedure, which takes care of initializing classes in a multithreaded environment.
Executing static blocks considered to be a part of class initialization:
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class...
It is guaranteed by JVM specification that that will be done in thread safe way. To quote JLS section 12.4.2 Detailed Initialization Procedure:
Because the Java programming language 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...
In more detail, it's implemented by acquiring lock on Class object:
The procedure for initializing a class or interface is then as follows:
Synchronize (§14.19) on the Class
object that represents the class or
interface to be initialize
Your method is static synchronized and it requires lock on Class object as well. Since the same lock is acquired by JVM during class initialization it's not possible for one thread to initialize class and for other execute static synchronized method on it.
All quotes are taken from
JLS
I hope that's helpful. Btw, how do you know that print occurs before class initialization finishes?
EDIT: Actually I'm wrong about assumption that only static synchronized couldn't be executed in parallel with class initialization. Any methods on class couldn't be executed until class initialization finishes.
If your "multi thread environment" uses multiple class loaders to load your Client class it would be possible for you to get mulitple Client instances, each one of which would run the static initialiser prior to running any Client.print() calls. You would see something like
doSomething
hello
doSomething
hello
hello
hello
I have some sample code which shows this but the current version is a little fiddly to run. If you want I can clean it up and post it.
If the code is running in some containers such as Servlet, you could initialize it in container’s lifecycle.