Java class loading mechanism - class loading process (initialization)

The whole process of the Java virtual machine loads classes include: loading, validation, preparation, resolution, initialization. Validation, preparation, called to resolve the connection process. Today we are talking about initialization.

The final step is to initialize class load class, in front of the class load, by addition to defining class loader from participation, remaining completely dominated operation and control of the virtual machine by the user application in the loading phase. To the initialization phase, really began to execute Java code in the class definition (or byte code) .

During the preparation phase, the variable has been assigned an initial value once the system requirements, and in the initialization phase, then go according to plan subjective programmers to develop a program to initialize class variables and other resources, or can be expressed from another point of view: the initialization phase is executed during the clinit class constructor () method. We will explain below clinit () method is how to generate, and look under before clinit () method performs the process of some of the features and details that may affect the behavior of programs running.

  • the clinit () method is implemented by the compiler automatically collected class assignment operation all class variables and static block of statements (static {} block) statements merger sequentially compiler collected appeared by the statement in the source file order determined, static statements can only block access to static variables before the statement block defined after him he could only variable assignment, can not access
  • clinit () constructor method with different class constructor calls the parent class, he does not need to be displayed, the virtual guarantee clinit subclass () method before the execution, clinit parent class () method has already been implemented. Thus clinit first class is executed in a virtual machine () method must be java.lang.Object
  • Since clinit parent class () method executes first, which means a static block of statements as defined in the parent class takes precedence over variable subclass assignment. Is of the following code: 2

public class Main {
    static class Parent{
        public static int A = 1;
        static {
            A =2;
        }
    }
    
    static class Sub extends Parent{
        public static int B = A;
    }
    
    public static void main(String args[]){
        System.out.println(Sub.B);
    }

}

  • the clinit () method for the class or interface is not necessary, if a class is not a static block of statements, there is no assignment of the variable, then the compiler can not generate the clinit this class () method. (Point where the first echo)
  • Interface block static statement can not be used, but there is still initialized variable assignment, so that, as there is the clinit () method of the class interface. But the two are different, clinit implements the interface () method does not need to perform the clinit () method of its parent interface. Only when the parent variables defined in the interface using parent interface will be initialized. Further, the interface implementation class is not the same when initialization clinit interface to perform () method
  • Virtual opportunity to ensure clinit a class () method is properly locked in a multi-threaded environment, synchronization, if multiple threads to initialize a class at the same time, then there will only be one thread to perform clinit () method, the other block waiting, until the clinit () method is executed. If () method takes a long time has operations in clinit a class, multiple processes may cause obstruction. Code demonstrates this scenario, the following

public class Main {
    static class DeadLoopClass{
        static {
            if (true) {
                System.out.println(Thread.currentThread() + "init DeadLoopClass");
                while (true) {

                }
            }
        }
    }
    
    public static void main(String args[]){
        Runnable script = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread() + "start");
                DeadLoopClass dlc = new DeadLoopClass();
                System.out.println(Thread.currentThread() + "run over");
            }
        };
        
        Thread thread1 = new Thread(script);
        Thread thread2 = new Thread(script);
        thread1.start();
        thread2.start();
    }

}

输出:
Thread[Thread-1,5,main]start
Thread[Thread-0,5,main]start
Thread[Thread-1,5,main]init DeadLoopClass

Show a thread long operation in an endless loop simulation, another wait in blocking

Guess you like

Origin blog.csdn.net/huqianlei/article/details/90741856