Is Java class initialized by the thread which use it for the first time?
Lets assume following classes definition:
public class A {
public final static String SOME_VALUE;
static {
SOME_VALUE = "some.value";
}
}
public class B {
private final String value = A.SOME_VALUE;
}
Assuming that the class A hasn't be开发者_如何学运维en loaded yet, what does happen when object of the class B is instantiated by some thread T? The class A has to be loaded and instantiated first. But my question is: if it's done in context of the thread T, or rather in context of some other (special) "classloader" thread?
Take a look at sections 12.4.1 ("When Initialization Occurs") and 12.4.2 ("Detailed Initialization Procedure") of the JLS:
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 initialized. This involves waiting until the current thread can obtain the lock for that object (§17.1).
- If initialization is in progress for the class or interface by some other thread, then wait on this Class object (which temporarily releases the lock). When the current thread awakens from the wait, 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 Class object and complete normally.
- If the class or interface has already been initialized, then no further action is required. Release the lock on the Class object and complete normally.
...
The specification states that initialization occurs in the current thread (meaning whatever thread reached a state which causes the need to initialize the class in question) but that the JVM implementation must make some pretty strict synchronization guarantees to avoid any problems.
There is no special thread for loading classes. It will be from the thread which refers to the class for the first time. The ClassLoader.loadClass method is synchronized so that multiple threads trying to load the same class don't interfere.
EDIT Code to enumerate
public class Arbit {
public static void main(String[] args) throws Exception{
B b1 = new B("1");
B b2 = new B("2");
B b3 = new B("3");
b1.start();
b2.start();
b3.start();
b1.join();
b2.join();
b3.join();
}
}
class B extends Thread{
B(String s){
setName(s);
}
@Override
public void run() {
try {
Thread.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
}
System.out.println(A.s);
}
}
class A{
static String s = Thread.currentThread().getName();
}
精彩评论