I am not sure whether I have a correct model of Java initialization mechanism in my head. Each class follows the following:
Initialize superclass, if there exists one
Initialize yourself
Initialize follows the following:
Initialize static and instance variables which have their values set outside of initializer.
Run static initialization block
Run constructor block
Is that precise/correct?
Code execute as below -
Static init blocks run once, when the class is first loaded.
Static Variable
All Super Constructor.
Instance init blocks run after the constructor's call to super().
instance variable.
(Init blocks execute in the order they appear.)
According to the Java language specification, your assumptions are more or less correct. The exceptions are that:
instance variables are run when the class is constructed (together with the constructor) after the class is initialized,
final static variables with compile-time constant expressions are loaded before even attempting to load the superclass, and
the static initialization block is run together with the static variables as one block, in the order they appear in the code.
Related
I know that static variables are common for all instances and instance variables can be different for different variables. But, when I initialize a static variable in a constructor, the static variable can be different for different instances. Why doesn't Java give me an error when I do this?What is the point of static variables if it changes when I initialize it in a constructor?
Updating the value of the static variable in a constructor can make sense in some scenarios.
The first example I can think of is a static counter variable that counts the number of instances created for a given class. You'd increment that variable inside the constructor.
public class SomeClass
{
private static int instanceCounter = 0;
public SomeClass()
{
...
instanceCounter++;
...
}
}
Another example would be lazy initialization of a static variable. You may want to initialize a static variable only when the first instance of the class is initialized (which means inside a constructor).
Why doesn't Java give me an error when I do this?
Because it is not a Java error. It may be a mistake in your program, but it could also be exactly what is required. The compiler simply has no way of "knowing".
(A compiler that says "error" for something that is not an error is a really bad idea. It only encourages people to turn off the error / warning messages.)
What is the point of static variables if it changes when I initialize it in a constructor?
Static variables can be used for all sorts of things, and some of them include global counters (see #Eran's example) or "most recent" values or state changes. Any of these could be updated in a constructor.
I want to add the following code to my class:
static private final ILogic_P logicInstanceI =
(ILogic_P)Factory.CreateAnon("some.path.ILogic_P" + (SomeClass.isIMDB() ? "1" : "2"));
public static ILogic_P getLogicInstanceI(){
return logicInstanceI;
}
I can't figure it out if the initialization of the static variable is thread safety or not.
Is there a chance that two threads will try to initialize this attribute simultaneously?
The answer is given by the Java Language Specification §12.4.2:
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 by using the following procedure. […]
Note the last sentence starting with “The implementation of the Java Virtual Machine is responsible for taking care …”
So you are not responsible for synchronization in the case of class initialization, and assigning initial values to static variables is part of the class initialization, as specified in §8.3.2:
8.3.2. Field Initialization
If a declarator in a field declaration has a variable initializer, then the declarator has the semantics of an assignment (§15.26) to the declared variable.
If the declarator is for a class variable (that is, a static field), then the following rules apply to its initializer:
…
At run time, the initializer is evaluated and the assignment performed exactly once, when the class is initialized (§12.4.2).
I found a lot of posts on static initialization blocks, however I'm trying to get a little better picture about the execution order and the reason for it. The code below prints out the text in both the static blocks and "then" prints out the text in the main static block.
I understand the way the compiler calls this is to do all the static blocks in order when the class is loaded and then access the main method. But since the main method itself is static, why not execute that in order of the other static blocks (Not even sure if its useful, just trying to understand a concept and if there's a pressing reason for it being done this way). What if there's static block we want to run after the main block?
class Cat {
static
{
System.out.println("This block welcomes you first");
}
public static void main(String[] args)
{
System.out.println("Meow world ");
}
static
{
System.out.println("This block welcomes you after");
}
}
Actual Output
This block welcomes you first
This block welcomes you after
Meow world
Why not?
This block welcomes you first
Meow world
This block welcomes you after
Static initializers are executed as soon as the class is loaded. The main method is called after the class has been loaded.
This section of the JLS discusses the sequence of events (12.1.3-4):
12.1.3. Initialize Test: Execute Initializers
In our continuing example, the Java Virtual Machine is still trying to execute the method main of class Test. This is permitted only if the class has been initialized (§12.4.1).
Initialization consists of execution of any class variable initializers and static initializers of the class Test, in textual order. But before Test can be initialized, its direct superclass must be initialized, as well as the direct superclass of its direct superclass, and so on, recursively. In the simplest case, Test has Object as its implicit direct superclass; if class Object has not yet been initialized, then it must be initialized before Test is initialized. Class Object has no superclass, so the recursion terminates here.
12.1.4. Invoke Test.main
Finally, after completion of the initialization for class Test (during which other consequential loading, linking, and initializing may have occurred), the method main of Test is invoked.
The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code. And dont forget, this code will be executed when JVM loads the class. JVM combines all these blocks into one single static block and then executes. Here are a couple of points I like to mention:
If you have executable statements in the static block, JVM will automatically execute these statements when the class is loaded into JVM.
If you’re referring some static variables/methods from the static blocks, these statements will be executed after the class is loaded into JVM same as above i.e., now the static variables/methods referred and the static block both will be executed.
After that the main method will execute.
Thanks
Static initializers are executed as soon as the class is initialized (a class can be loaded and initialized at a later point of time. check Class.forName()). The main() method is called after the static initializers are executed. So the output is like that.
In the code below, what is the order of initialization of data fields? What is the general rule followed by java for data member and member functions?
public class TestClass
{
int j=10;
static int h=5;
public static void main(String[] args)
{
TestClass obj= new TestClass();
}
}
In general:
1) static field members (static initializers in general)
2) non-static field members
3) constructor
However you can test it with a snippet of code like this:
public class TestClass {
int i = 10;
static int j = 20;
public TestClass() {
// TODO Auto-generated constructor stub
System.out.println(i);
i = 20;
System.out.println(i);
}
public static void main(String[] args) {
new TestClass();
}
}
Quoting from the great "Thinking In Java":
Within a class, the order of initialization is determined by the order that the variables are
defined within the class. The variable definitions may be scattered throughout and in between method definitions, but the variables are initialized before any methods can be
called—even the constructor.
...................................
There’s only a single piece of storage for a static, regardless of how many objects are created.
You can’t apply the statickeyword to local variables, so it only applies to fields. If a field is a
staticprimitive and you don’t initialize it, it gets the standard initial value for its type. If it’s
a reference to an object, the default initialization value is null.
To summarize the process of creatingan object, consider a class called Dog:
Even though it doesn't explicitly use the static keyword, the constructor is actually a
static method. So the first time an object of type Dog is created, or the first time a
static method or static field of class Dog is accessed, the Java interpreter must
locate Dog.class, which it does by searching through the class path.
As Dog.class is loaded (creating a Class object, which you’ll learn about later), all of
its static initializers are run. Thus, static initialization takes place only once, as the
Class object is loaded for the first time.
When you create a new Dog( ), the construction process for a Dog object first
allocates enough storage for a Dog object on the heap.
This storage is wiped to zero, automatically setting all the primitives in that Dog
object to their default values (zero for numbers and the equivalent for boolean and
char) and the references to null.
Any initializations that occur at the point of field definition are executed.
Constructors are executed.This might actually involve a fair amount of activity, especially when inheritance is involved.
Here is the order.
Static fields initialized and static block executed at class loading time, they will be initialized in the same order they declared.
Set fields to default initial values (0, false, null)
Call the constructor for the object (but don't execute the body of the constructor yet)
Invoke the constructor of the superclass
Initialize fields using initializers and initialization blocks
Execute the body of the constructor
I think you're just missing section 12.4.2 of 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.
So Finally Here is Order which you are searching for:
Initialization blocks run in the order they appear in the program.
Static initialization blocks run when the class is first loaded into JVM
Instance initialization blocks run whenever a new instance of class is created.
Our application is using initialization code that depends on the order static code is executed and I'm wondering if this order will be consistent across all JVMs.
Here is a sample of what I mean:
public class Main {
static String staticVar = "init_value";
public static void main(String[] args) {
System.out.println(A.staticVar);
staticVar = "mainValue";
System.out.println(A.staticVar);
}
}
public class A {
static String staticVar = Main.staticVar;
}
will give:
init_value
init_value
and
public class Main {
static String staticVar = "init_value";
public static void main(String[] args) {
// System.out.println(A.staticVar);
staticVar = "mainValue";
System.out.println(A.staticVar);
}
}
public class A {
static String staticVar = Main.staticVar;
}
will give (on my environment):
mainValue
To summarize, across all JVMs, is static code always executed when we use a class for the first time?
EDIT: Despite all the reassurances below, if you're thinking of relying on this sort of thing, I would try hard to refactor your code so that it doesn't crop up. While it is guaranteed to work, it's also likely to make your code very brittle. The fact that static initializers get called "invisibly" makes them relatively hard to reason about and debug.
Yes, this is guaranteed by the language specification. From section 8.7 of the spec:
Any static initializers declared in a class are executed when the class is initialized and, together with any field initializers (§8.3.2) for class variables, may be used to initialize the class variables of the class (§12.4).
StaticInitializer: static Block
It is a compile-time error for a static initializer to be able to complete abruptly (§14.1, §15.6) with a checked exception (§11.2). It is a compile-time error if a static initializer cannot complete normally (§14.21).
The static initializers and class variable initializers are executed in textual order.
And from section 12.4:
Initialization of a class consists of
executing its static initializers and
the initializers for static fields
declared in the class. Initialization
of an interface consists of executing
the initializers for fields declared
in the interface.
Before a class is
initialized, its direct superclass
must be initialized, but interfaces
implemented by the class need not be
initialized. Similarly, the
superinterfaces of an interface need
not be initialized before the
interface is initialized.
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 field is not a
constant variable (§4.12.4).
T is a
top-level class, and an assert
statement (§14.10) lexically nested
Static initialisers (e.g. your staticVar declarations) are always executed when you use a class for the first time.
Static methods are only executed when they are called. In your case, this is happening because the static void main(String[] args) is the entry point to your application. But if you defined a different static method then it would not be called.
It is also possible to create a static initialiser block that will also be called automatically before the class is first used, e.g.
static {
// some initialisation code here
}
That should be all the same on all platforms. See JVM Specification : http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#19075
A quote from Java specification:
Initialization of a class consists of
executing its static initializers and
the initializers for static fields
declared in the class. Initialization
of an interface consists of executing
the initializers for fields declared
in the interface.
Yes, according to the Java Language Specification static code is always executed in the same order on all (compliant) JVM's.
8.7 Static Initializers
The static initializers and class variable initializers are executed in textual order.
Dittos to other posters, but let me add that a static initializer that depends on the state of other classes like in your example seems to me to make for very fragile and difficult-to-maintain code. I'll use static intializers to populate internal class data -- to fill up an array with default values or that sort of thing. But I don't think I've ever had one peek at the data in another class. Technically legal, and maybe there are odd cases where it's a good idea, but yuck.
Yes, I believe that would be the point by definition.
Static Block will always run first not just the first time... Before executing any code block, JVM execute the static code block first, and then only it run the code block as it has been designed...