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.
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 writen the small java class which I want to load by using ClassLoader.
public class ClassLoadingObj {
public ClassLoadingObj(){
System.out.println("---instantiating ClassLoadingObj ");
}
static{
System.out.println("---Loading ClassLoadingObj");
}
}
But when I executed the following code:
ClassLoader.getSystemClassLoader().loadClass("com.st.classLoader.ClassLoadingObj");
I find that the static block does not get executed. My question is that if a class is loaded by using the loadClass() method, why are static blocks not executed in comparison to instantiating a class where static blocks always get executed.
Actually static block gets executed when the class is initialized and it's a little bit different from loaded.
Before initialized class is linked and before that it is loaded, so there are 3 (or 4, including not-loaded) states of class.
Here is well described how it works and what are the requirements for a class to become initialized.
An excerpt:
The Java virtual machine specification gives implementations
flexibility in the timing of class and interface loading and linking,
but strictly defines the timing of initialization. All implementations
must initialize each class or interface on its first active use. The
following six situations qualify as active uses:
A new instance of a class is created (in bytecodes, the execution of a new instruction. Alternatively, via implicit creation,
reflection, cloning, or deserialization.)
The invocation of a static method declared by a class (in bytecodes, the execution of an invokestatic instruction)
The use or assignment of a static field declared by a class or interface, except for static fields that are final and initialized
by a compile-time constant expression (in bytecodes, the execution
of a getstatic or putstatic instruction)
The invocation of certain reflective methods in the Java API, such as methods in class Class or in classes in the
java.lang.reflect package
The initialization of a subclass of a class (Initialization of a class requires prior initialization of its superclass.)
The designation of a class as the initial class (with the main()< method) when a Java virtual machine starts up
There are two types of class loader in java. Maybe the ClassLoader you use is the
java.lang.ClassLoader, but the system won't use the this ClassLoader. You can try
com.sun.org.apache.bcel.internal.util.ClassLoader.getSystemClassLoader(), it will execute
the static block. More information you can reference to this
page (http://en.wikipedia.org/wiki/Java_Classloader#Class_Loaders_in_JEE)
In the following scenario ,
import A;
public class B{
static A a;
static{
a = new A();
}
}
Is it possible that the static initialization block gets called before a is properly initialized? Note: A here is a logging framework.
In the case you mention above static block will be called before A is initialized as static block will be called when class loads (Class B in your case). So when you do
B.someStaticMethod()
First class B will be loaded where static block is called with it(One time process in JVM) and then static method will be called.
Also Note that Importing statement to load the class does not load the class. It happens when yo do some operation on that class.
Imports have nothing to do with it. There are no imports at runtime.
Referenced classes are loaded during the linking phase, which precedes the initialization phase. In this case A is loaded during the link resolution step for B, before B's static initializer executes.
Reference: JVM Specification: Loading, Linking, and Initializing.
First, it is possible, but not certain, that the static initializer would be called before A is "properly initialized." The static initializer will be executed when B is is loaded by the classloader (see #9: http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2). We don't have enough information from what you've given to know when that will happen relative to A being loaded (the constructor invocation in B's static initializer might be the first time A is loaded, or it might have happened long before).
Second, it's entirely likely that an instance of A being initialized will trigger the initialization of A in a way such that everything will work itself out. Keep in mind that A's constructor won't execute until the class is loaded, which would include running any static initializers for A. So I'm not sure what type of initialization you're worried about that might not happen.
Third, the import statement has nothing to do with any of this. It would behave the same whether you fully qualified com.foo.A used an import statement.
Finally, it would probably be helpful if you provided a real example. If A is just a logging framework, then it's not anything proprietary and you'll probably get a more helpful answer based on what will really happen with that specific framework.
Edit: see the link provided in the comment below for a concrete example.
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.
Documentation
In order to that it is not possible that the static block gets called before A is properly initialized.
I think there would be no confusion if you initialize your static instance like -
static A a = new A();
static A a;
static{
a = new A();
}
what this code clearly mean is code a = new A(); will be called and initialized only once and remain in permanent generation when class is loaded till main thread exit from the system.
I have 2 jars, let's call them a.jar and b.jar.
b.jar depends on a.jar.
In a.jar, I defined a class, let's call it StaticClass. In the StaticClass, I defined a static block, calling a method named "init" :
public class StaticClass {
static {
init();
}
public void static init () {
// do some initialization here
}
}
in b.jar, I have a main, so in the main, I expect that the init() method has been called, but actually not. I suspect that is because the StaticClass has not been loaded by the jvm, could anyone tell me
Is my conclusion correct?
What triggers the jvm to load a class?
How can I get the static block executed automatically?
Thanks
Yes, you are right. Static initialization blocks are run when the JVM (class loader - to be specific) loads StaticClass (which occurs the first time it is referenced in code).
You could force this method to be invoked by explicitly calling StaticClass.init() which is preferable to relying on the JVM.
You could also try using Class.forName(String) to force the JVM to load the class and invoke its static blocks.
Yes you are right, since you are not using your StaticClass it is not loaded by the vm and therefore init() is never executed.
For your second question, you probably have to go the hard way and scan all available classes and load them.
https://stackoverflow.com/a/3223019/393657
First of all class loading is different than class initialization. For anyone looking for explanation from Java Language Specification, when is static block executed - here it is.
The JLS §8.7 says that :
A static initializer declared in a class is executed when the class is initialized (§12.4.2).
So what does the initialization mean? Let's refer to JLS §12.4.2. This describes detailed initialization procedure. However point JLS §12.4.1 might be more appropriate here. It says that :
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 (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
So to make the static initializer block to be executed automatically, you have to force one of those options to happen.
You are right, the easiest way is to access the class, for instance do a
StaticClass.class.newInstance();
Or something to that respect in your main method. This will ensure the class is loaded by the classloader.
The static code is executed when your class (StaticClass I guess) is referenced.
Thus, it should be executed if you create a new instance of StaticClass or if you call one of its static methods.
Static block is executed when a loaded class is initialized or referenced first. Loading class doesnt mean that class is to initialized. JVM Class Loading is separate things to concern.
Yes, the static initializer will be executed when the class is loaded. This normally occurs when you access the class in the class loading context for the first time.
in b.jar main method class should extend that StaticClass then automatically that static block and init() will be invoked
Adding some more:
static block will be executed when jvm load class.
Here in your example you can call init() method of your StaticClass by intantiating class
like
StaticClass staticClass=new StaticClass();
or
StaticClass.class.newInstance(); this is more preferebal
Imagine a Java class which has most features that you can find in a class. For example: it inherits from another class, implements a couple of interfaces, includes some 'static final' constants, some final constants, some static variables, instance variables, a static block, an unnamed code block (just code in {}), constructors, methods etc.
When the class in question is loaded into the JVM for the first time, in what order are the various portions of the class initialized or loaded into the JVM? What does the call stack in the JVM look like for the loading? Assume that only one classloader is at work here.
This is going back to the absolute basics/internals of Java, but I havent been able to find a good article explaining the correct sequence.
This could be described in the section 2.17.4 of the JVMS 5.0/6
2.17.4 Initialization
Initialization of a class consists of:
executing its static initializers (§2.11) and
the initializers for static fields (§2.9.2) declared in the class.
Initialization of an interface consists of executing the initializers for fields declared in the interface (§2.13.3.1).
Before a class or interface 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 one of the following occurs:
T is a class and an instance of T is created.
T is a class and a static method of T is invoked.
A nonconstant static field of T is used or assigned. A constant field is one that is (explicitly or implicitly) both final and static, and that is initialized with the value of a compile-time constant expression. A reference to such a field must be resolved at compile time to a copy of the compile-time constant value, so uses of such a field never cause initialization.
Invocation of certain methods in library classes (§3.12) also causes class or interface initialization. See the Java 2 platform's class library specifications (for example, class Class and package java.lang.reflect) for details.
The intent here is that a type have a set of initializers that put it in a consistent state and that this state be the first state that is observed by other classes. The static initializers and class variable initializers are executed in textual order and may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope. This restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.
Before a class or interface is initialized its superclass is initialized, if it has not previously been initialized.
The updated version of Initialization in JVMS 8 is in Chapter 5.5
Initialization of a class or interface consists of executing its class or interface initialization method (§2.9).
A class or interface may be initialized only as a result of:
The execution of any one of the Java Virtual Machine instructions new, getstatic, putstatic, or invokestatic that references the class or interface (§new, §getstatic, §putstatic, §invokestatic).
All of these instructions reference a class directly or indirectly through either a field reference or a method reference.
Upon execution of a new instruction, the referenced class or interface is initialized if it has not been initialized already.
Upon execution of a getstatic, putstatic, or invokestatic instruction, the class or interface that declared the resolved field or method is initialized if it has not been initialized already.
The first invocation of a java.lang.invoke.MethodHandle instance which was the result of resolution of a method handle by the Java Virtual Machine (§5.4.3.5) and which has a kind of 2 (REF_getStatic), 4 (REF_putStatic), 6 (REF_invokeStatic), or 8 (REF_newInvokeSpecial).
Invocation of certain reflective methods in the class library (§2.12), for example, in class Class or in package java.lang.reflect.
The initialization of one of its subclasses.
Its designation as the initial class at Java Virtual Machine start-up (§5.2).
Prior to initialization, a class or interface must be linked, that is, verified, prepared, and optionally resolved.
Because the Java Virtual Machine 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.
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 Class object is verified and prepared but not initialized.
This Class object is being initialized by some particular thread.
This Class object is fully initialized and ready for use.
This Class object is in an erroneous state, perhaps because initialization was attempted and failed.
How about the JLS, specifically section 12.4?