Real java virtual machine (five) - Class loading

Foreword


An article on the structure of simple learning Class files, this time to see how the virtual machine to load Class files, and what to do after the additional processing load

 

Class file loading process


  Class file loading process can be divided into load 3 is connected and initialization step, wherein the connector is divided into verification, preparation and analytical step 3, the overall process is as follows in FIG.

 

1. Class loading conditions

  Class file is loaded only when you must use, Java virtual machine provides a class or interface prior to initial use, it must be initialized. Here is the use of active use, only the following circumstances will actively use

  • When creating an instance of the class, such as the new keyword or reflective, cloning, deserialization
  • Class static method call, i.e. using a bytecode instruction invokestatic
  • Static field uses a class or interface (except the final constant), such as the use or putstatic instruction getstatic
  • When using reflection methods class package java.lang.reflect
  • Subclass initialization request to initialize the parent class
  • As a start the virtual machine that contains the main method of the class

In addition to initializing the above situation is an active use, the rest are passive use, passive use will not cause class

Actively using readily understood, the following examples give an easy to use passive memory

public class Parent {
    static{
        System.out.println("Parent init");
    }
    public static int v = 100;
}

public class Child extends Parent{
    static {
        System.out.println("Child init");
    }
}

public class Test1 {
    public static void main(String[] args) {
        System.out.println(Child.v);
    }
}

Output operation code following the above

Parent init
100

Although direct access to a subclass object Test1, but it has not been initialized Child, Parent only be initialized, we can see, when you use a field, only to directly define the class of the field will be initialized (though here Child it is not initialized, but it has been loaded, but did not enter the initialization phase)

Use -XX: + TraceClassLoading running this code, the following log can be obtained (only a small portion taken)

[Loaded com.xxxx.Parent from file:/D:/ideaWorkSpace/xxxx/target/classes/]
[Loaded com.xxxx.Child from file:/D:/ideaWorkSpace/xxxx/target/classes/]
Parent init
100

We can see the two classes have been loaded into the system

 

2. Load class

  Loading a class is the first class loading stage. When the class is loaded, the virtual machine to do the following:

  • Binary data by the full name of the class to get a class of stream
  • Binary data stream analysis method of the class data structure area
  • Create an instance of java.lang.Class class which represents the type

  Binary data stream from the class Class file system, and the like may be a zip file to extract class files may be loaded from the network, and even some Class binary information generated at runtime. After obtaining the binary information, Java virtual machine to process the data and, ultimately, an instance of java.lang.Class, Class example is the type metadata access interface, but also to achieve critical reflection data.

 

3. Verify class

  Class loading into the system after the start of the connecting operation, the first step is to connect verification, the purpose is to ensure loading bytecode is legal, reasonable and compliant, more complex verification steps, to check needs to be done substantially below:

 

 

4. Prepare

  When the class verification by, the virtual machine will enter the stage of preparation. This stage, the virtual machine for the class assigned to the appropriate memory space, and set the initial value. The initial value of each type of the variable in the following table

Each type variable default initial value
Types of Default initial value
int 0
long 0L
short (short)0
char \ U0000
boolean false
reference null
float 0f
double 0f

Java does not support boolean type, actually for boolean int, int because the default is 0, so the default is false boolean

If there is a constant class field, then the field will include the correct constant value at the preparation stage.

 

5. Parse class

  The third step is to parse the connection phase, working phase is to resolve the symbol classes, interfaces, fields and methods reference into direct reference. Symbolic references that some literal references, regardless of the virtual machine internal data structures and memory layout. In the Class class file, a lot of symbolic references through the constant pool.

invokevirtual #24 <java/io/PrintStream.priintln>

  This is System.out.println () bytecode, it can be seen that the use of a constant pool 24, to view and analyze the constant pool, the following structure can be seen

 

 

 The constant pool of 24 cited invokevirtual, along CONSTANT_Methodref reference relationship # 24 of search, eventually found a reference to all Class and NameAndType types are based on the string. Therefore, it is considered invokevirtual function call through a reference to literal description has been clear. This is symbolic references.

  Actually running only symbolic references are not enough, when the method is called, the system needs to know exactly the location method. In a method, for example, Java virtual machine for each method are a method of preparing a table, all of the methods listed, when you need to call a method of a class, just know that this method is offset in the method of the table on It can be called directly. By parsing operation, reference symbol position may be converted to the target method in the method table of the class.

  In summary, it is to resolve the symbolic reference is converted to a direct reference, to give the class, field or method pointer or offset in memory.

 

6. initialization

  Initialization is the final stage of class loading. If the previous steps have no problem, it represents a class can successfully loaded into the system. At this point, the class will begin to execute Java byte code. Initialization method important task is to perform class initialization phase of <clinit>. The method <clinit> is automatically generated by the compiler, which is a static member and a static assignment statement block co-produced.

public class SimpleDemo {
    public static int id = 1;
    public static int number;
    static {
        number = 4;
    }
}

The above example of this class, as the compiled bytecode

public class SimpleDemo {
     <ClassVersion=52>
     <SourceFile=SimpleDemo.java>

     public static int id;
     public static int number;

     public SimpleDemo() { // <init> //()V
         <localVar:index=0 , name=this , desc=LSimpleDemo;, sig=null, start=L1, end=L2>

         L1 {
             aload0 // reference to self
             invokespecial java/lang/Object.<init>()V
             return
         }
         L2 {
         }
     }

     static  { // <clinit> //()V
         L1 {
             iconst_1
             putstatic SimpleDemo.id:int
         }
         L2 {
             iconst_4
             putstatic SimpleDemo.number:int
         }
         L3 {
             return
         }
     }
}

See, <clinit> method of generation, integration of static assignment of the class and the static block of statements, and successively id number assignment.

As mentioned earlier before loading a class, the virtual machine will always try to load the class of the parent class, so the parent class <clinit> method is always called before <clinit> subclass, that is, a subclass of static block is performed after the parent class.

Not all classes will have a <clinit> method, if a class has no assignment, there is no static statement block, the compiler does not generate <clinit> methods for the class.

Another important point is that virtual machine thread-safe <clinit> method performed when multiple threads try to initialize the same class, only one thread can enter <clinit> method, if the first thread successfully executed, behind the thread will not execute the way to go.

Also due <clinit> is locking thread-safe, so when the class is initialized, it may lead to a deadlock in a multithreaded environment, and this deadlock is difficult to find. Here's an example of deadlock

class StaticA{
    static{
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e){

        }
        try {
            Class.forName("com.blog.test.StaticB");
        } catch (ClassNotFoundException e){

        }
        System.out.println("com.blog.test.StaticA init success");
    }
}

class StaticB {
    static{
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e){

        }
        try {
            Class.forName("com.blog.test.StaticA");
        } catch (ClassNotFoundException e){

        }
        System.out.println("com.blog.test.StaticB init success");
    }
}

public class StaticDeadLockMain extends Thread {
    private char flag;
    public StaticDeadLockMain(char flag){
        this.flag = flag;
        this.setName("Thread"+flag);
    }

    @Override
    public void run() {
        try {
            Class.forName("com.blog.test.Static" + flag);
        } catch (ClassNotFoundException e){
            e.printStackTrace();
        }
        System.out.println(getName() + "over");
    }

    public static void main(String[] args) {
        StaticDeadLockMain loadA = new StaticDeadLockMain('A');
        loadA.start();
        StaticDeadLockMain loadB = new StaticDeadLockMain('B');
        loadB.start();
    }
}

The above code simply another class is a static class initialization code block, each formed seize resource to initialize. The code executing main method, has been the main method is not stopped, there is no output, the stack information see below jstack

 Stack information did not have enough information to determine the deadlock, but a deadlock does exist, so when we initialize the class, to be extra careful this deadlock situation.

Guess you like

Origin www.cnblogs.com/gtblog/p/11654875.html