views:

74

answers:

2

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 been 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?

+3  A: 

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();
}
saugata
I believe from JDK7 you can have two classes from the same class loader initialising at the same time.
Tom Hawtin - tackline
@Tom But wouldn't that cause problems e.g. if in an equals method I put this.getClass() == obj.getClass()
saugata
@saugata Each individual class will be initialised once, but there may be multiple different classes in the same class loader the are initialised at the same time. This can't currently happen because of the lock noted in your answer. (I think this is right.)
Tom Hawtin - tackline
OK ... I got a bit confused, will check it out.
saugata
+4  A: 

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:

  1. 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).
  2. 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.
  3. 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.
  4. 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.

matt b
+1 for referencing the JLS
medopal