I recently came across this at work. While I am not sure it is really a good idea, I don't understand how static blocks are handled by the compiler.
Here is an example:
Consider that you have classes A and B:
public class A {
public final static List<Integer> list;
static {
list = new ArrayList<>();
}
}
public class B {
public final static int dependsOnA;
static {
dependsOnA = A.list.size();
}
}
And a main class that just reads B.dependsOnA.
The static block in B is dependent of the one in A, since it uses the list static variable.
Now, the code executes properly and no NullPointerException is raised at runtime. But what is the mechanism that ensures that list is initialized before it is potentially used elsewhere?
The mechanism is described in detail here, but the five most important points are:
Before a class is referenced, it needs to be initialised.
If initialisation of a class has already begun (or if it's finished), it isn't attempted again.
Before a class is initialised, all its superclasses and superinterfaces need to be initialised first.
Static initialisers within a single class are executed in textual order.
Implemented interfaces are initialised in the order in which they appear in the implements clause.
These rules completely define the order in which static blocks are executed.
Your case is rather simple: before you access B.dependsOnA, B needs to be initialised (rule 1), the static initialiser is then trying to access A.list, which triggers the initialisation of class A (again rule 1).
Note that there's nothing stopping you from creating circular dependencies this way, which will cause interesting things to happen:
public class Bar {
public static int X = Foo.X+1;
public static void main(String[] args) {
System.out.println( Bar.X+" "+Foo.X); //
}
}
class Foo {
public static int X = Bar.X+1;
}
The result here is 2 1 because the way the initialisation happens is this:
Bars initialisation begins.
Bar.Xs initial value is evaluated, which requires initialising Foo first
Foos initialisation begins.
Foo.Xs initial value is evaluated, but since Bars initialisation is already in progress, it isn't initialised again, Bar.Xs "current" value is used, which is 0, thus Foo.X is initialised to 1.
We're back to evaluating Bar.Xs value, Foo.X is 1 so Bar.X becomes 2.
This works even if both fields were declared final.
The moral of the story is to be careful with static initialisers referring to other classes in the same library or application (referring to classes in a third party library or standard class library is safe as they won't be referring back to your class).
The "mechanism" is the JVM's classloader, which will ensure that a class' initalization blocks are executed (with a global lock across the whole JVM) before returning control flow to where the class was first referenced. It will first load class A only after referenced, in this case when B's init block references A.list.
During execution of the static block of B, the runtime encounters A for the first time, and it will invoke the static block of A before it accesses A.list.
No matter how you write the code, a static block is a static block and it will execute as part of the JVM loading a class.
When you say B.dependsOnA, B class starts geting loaded by the JVM and the static block in B gets called somewhere during this process. When you say dependsOnA = A.list.size();, class A starts getting loaded by the JVM and the static block in A will execute somewhere during this process which initializes the list. The statment list.size() will only execute after class A has been loaded completely by the JVM. Subsequently, the JVM can only finish loading class B after the static block in B completes.
This is the job of the class loader. The class loading in java starts with the bootstrap classloader. This class loader first loads all the classes in the standard java library, the rt.jar.
Then the extension classloader is invoked. This loads all the classes from the extension jar files installed in a JVM ext directory. Now finally the classpath classloader is invoked.
The classpath classloader starts loading classes from the main class, the class that has the main method defined. Once it is loaded, it executes any static initializers in that class. While in the execution of the initializer, if it encounters any class that is not loaded, it will pause the execution of the static block, loads the class first, and finally resumes the execution of that static block.
So, there is no chance that any calls to non-loaded classes to occur. Let's see this with your own example, whose code is like this:
class A
{
public final static List<Integer> list;
static
{
System.out.println("Loaded Class A");
list = new ArrayList<>();
}
}
class B
{
public final static int dependsOnA;
static
{
System.out.println("Loaded Class B");
dependsOnA = A.list.size();
}
}
Here in this example, there is actually no main method, so these classes won't actually be loaded into the memory. Suppose, let's add the following main class to the above code.
class C
{
static
{
System.out.println("Loaded Class C");
}
public static void main(String[] args)
{
System.out.println(B.dependsOnA);
}
}
Let's see what this would produce in the output: http://ideone.com/pLg3Uh
Loaded Class C
Loaded Class B
Loaded Class A
0
That is, first the class C is loaded, because it had the main method. Once it is loaded, the static initializer of class C is invoked. Notice, however, that the main method is invoked after the static block of class C is loaded.
Now the main method, we printed the value of dependsOnA of class B. Now, the class loader stops executing that statement, and loads the class B, and executes it's static block, which in turn, assigns the dependsOnA variable with the value of the number of elements in the list of class A, which is not loaded.
So the class loader jumps from there, loads the class now, and invokes the static block of the class A, and a list is created. Now since there are no more classes to load, the class loader comes back to the static block of class B, and assignment is complete. Now finally, the control is now with the main method, and the value of dependsOnA is printed to the console.
Hope this helps.
Here we have some explaination
Static Block in Java
If you call the A class first, the A static is called and A.list exists and will when B will call it.
If you call the B class first, the B static is called, cascading to the A call, calling its static block, where A.list is created.
We could see is its trickiest way:
B > B.static > A > A.static > A.list exists
The working is very simple JVM class loader, which will ensure that a class static blocks are executed when the class is first referenced.
1.If you have executable statements in the static block, JVM will automatically execute these statements when the class is loaded into JVM.
2.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.
Related
I have a class whose initialization takes quite a bit of time; it invokes a server and that server takes several minutes to become ready.
Methods on that class aren't called for quite a while and they are always called from a class that is automatically loaded on start-up. My set-up is like this:
class SlowToStartUp {
public static void init() {
// do nothing
}
static {
initiateConnectionToServer()
}
public static V invokeServer() {
waitForServerToConnect();
return valueFromServer();
}
}
class AlwaysLoaded {
static {
SlowToStartUp.init();
}
public void someMethod() {
V v = SlowToStartUp.invokeServer();
}
This strikes me as structurally correct. If there were no init() function at all, initiateConnectionToServer() wouldn't be called until someMethod() needed the class for the first time, and then there would be an unnecessary (and in my system, unacceptable) delay.
If I put the initiateConnectionToServer() call in init(), the interface would be more fragile (since the call might be forgotten).
But now I am wondering if I have outsmarted myself. The compiler can see that init() is empty. Could it not just optimize the call away? It does not do so now, but it that guaranteed?
I tried marking init() as volatile, but that is not allowed.
I am considering putting the actual initialization into init(), making sure it is idempotent, and invoking it from a static block, just to be on the safe side, but I thought I would ask for advice first.
One alternative approach would be to refactor to a singleton class instead of a bunch of static method. The singleton will then be created at startup and your initialization code would run right away.
public class SlowPokeSingleton {
private SlowPokeSingleton() { /* execute init code */ }
// created at startup
private final static SlowPokeSingleton instance = new SlowPokeSingleton();
public static SlowPokeSingleton instance() { return instance; }
}
You will need to call instance() to make sure the instance is actually created. You can add that to your server startup to be safe.
I have a tenuous answer to my own question. The events that trigger class initialization are specified in JLS 12.4.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.
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 within T is executed.
It seems to me that a compiler that optimized away an empty static function would violate the provision I marked in bold.
Comments welcome.
I agree with Giovanni Botta:
You could use a singleton pattern instead of static methods and fetch
the singleton instance as soon as your application starts. That would
force the JVM to create the instance and thus run your initialization
code. – Giovanni Botta
Specifically:
1) Put the "time consuming" part of your initialization into a private, static "init()" method.
2) Make your class's constructor "private".
3) Instead of a constructor, provide a public static "getInstance()" method to fetch a reference to your (already-initialized) singleton instance.
4) Your other methods can be non-static, if you wish.
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.
I tried to print something using static block without Main method.
But how do I know at the time of the class loading static block will be
called.
Here removing main method its not printing anything in CMD as well as in Eclipse IDE.
Output :(with main method)
Static Block Called........
i :6
public class StaticBlock
{
static int i = 5;
static
{
System.out.println("Static Block Called........");
i ++;
}
public static void main(String args[])
{
System.out.println("i :"+i);
}
}
This is actually a behavioral detail which has changed in Java 7.
Prior to Java 7, whatever class is passed to the JVM as the application entry point, that class is loaded, initialized, and then the main method is looked up. Even if there's no such method, the class initialization code will have run. That includes any static initializers.
As of Java 7, the class will be loaded, but will not be initialized prior to looking up the main method. The JVM will abort with an error if the method is not found, and initialization will never occur.
Class loading vs. initialization
For many purposes this is just a subtle difference, but you have actually hit one where it is crucial. As per Java Language / Java Virtual Machine specifications, there is a clear distinction between:
class loading: this happens at any time, and for any class, the specific JVM implementation sees fit. It means loading the binary contents of the .class file, parsing them, verifying the bytecode, building up the constant pool, and so on;
class initialization: this happens at a precisely specified point, which is when the class is referred to (explicitly or otherwise) for the first time during a JVM run. At this point all the class initializers run.
Your StaticBlock class will not be loaded unless it is not referred form somewhere. Having the main method causes your class to be loaded because jvm loads the class when you run it. As soon as you refer your StaticBlock class, anywhere in your project, be it the main method in the same class or the main method in a different class. That will cause the class to be loaded and as soon as class will be laoded, static block in that class will be executed.
By refer I mean either you create an instance of it or you use any public method or field of the class using hte class name i.e StaticBlock.filed or StaticBlock.method().
In short, a class static block is executed when the class gets loaded by a classloader.
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...
This question already has answers here:
What is the difference between a static and a non-static initialization code block
(9 answers)
Closed 8 years ago.
I was looking over some code the other day and I came across:
static {
...
}
Coming from C++, I had no idea why that was there. Its not an error because the code compiled fine. What is this "static" block of code?
It's a static initializer. It's executed when the class is loaded (or initialized, to be precise, but you usually don't notice the difference).
It can be thought of as a "class constructor".
Note that there are also instance initializers, which look the same, except that they don't have the static keyword. Those are run in addition to the code in the constructor when a new instance of the object is created.
It is a static initializer. It's executed when the class is loaded and a good place to put initialization of static variables.
From http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html
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.
If you have a class with a static look-up map it could look like this
class MyClass {
static Map<Double, String> labels;
static {
labels = new HashMap<Double, String>();
labels.put(5.5, "five and a half");
labels.put(7.1, "seven point 1");
}
//...
}
It's useful since the above static field could not have been initialized using labels = .... It needs to call the put-method somehow.
It's a block of code which is executed when the class gets loaded by a classloader. It is meant to do initialization of static members of the class.
It is also possible to write non-static initializers, which look even stranger:
public class Foo {
{
// This code will be executed before every constructor
// but after the call to super()
}
Foo() {
}
}
Static block can be used to show that a program can run without main function also.
//static block
//static block is used to initlize static data member of the clas at the time of clas loading
//static block is exeuted before the main
class B
{
static
{
System.out.println("Welcome to Java");
System.exit(0);
}
}
A static block executes once in the life cycle of any program,
another property of static block is that it executes before the main method.
Static blocks are used for initializaing the code and will be executed when JVM loads the class.Refer to the below link which gives the detailed explanation.
http://www.jusfortechies.com/java/core-java/static-blocks.php
yes, static block is used for initialize the code and it will load at the time JVM start for execution.
static block is used in previous versions of java but in latest version it doesn't work.