当前位置:网站首页>JVM class loading mechanism

JVM class loading mechanism

2022-04-23 17:30:00 God annoyed dog broke into your blog

JVM Class loading mechanism

summary

Java The virtual machine takes the data describing the class from Class File loaded into memory , And verify the data 、 Transform resolution and initialization , Finally, it can be directly used by virtual machine Java type , This process is called the class loading mechanism of virtual machine .

 Insert picture description here

Class loader and class loading process

Class loading process

 Insert picture description here

  • The classloader subsystem is responsible for loading from the file system or network Class file ,class The file has a specific file ID at the beginning of the file .
  • ClassLoader Only responsible for class Loading of files , As for whether it can run , By Execution Engine decision .
  • The loaded class information is stored in a block of memory called the method area . In addition to class information , The method area also holds runtime constant pool information , It may also include string literals and numeric constants ( This part of the constant information is Class Memory mapping for the constant pool part of the file )

Loading phase Loading

load (Loading) Phase is the loading of the entire class (Class Loading) A stage in the process . Don't confuse two different concepts .

Three things to do in the loading phase :

  1. Get the binary name that defines a class by the fully qualified name of the class .
  2. Convert the static storage structure represented by this byte stream into the data structure of the method area runtime .
  3. Generate a representation of this class in memory java.lang.Class object , As the access to all kinds of data of this class in method area .

Link phase Linking

verification Verify

The purpose is to ensure Class The byte stream of the file contains information that meets the requirements of the current virtual machine , Ensure the correctness of the loaded class , Does not harm the security of virtual machine itself .

It mainly includes four kinds of verification , File format validation , Metadata validation , Bytecode verification , Symbol reference validation .

1. File format validation

Mainly verify the file format specification

  • Whether to count by magic 0xCAFEBABE start .
  • Lord 、 Is the minor version number in the current Java Virtual machine acceptance range .
  • Is there an unsupported constant type in the constant of the constant pool ( Check constants tag sign ).
  • Is there any index value pointing to a constant that does not exist or does not conform to the type .
  • CONSTANT_Utf8_info Whether there is any inconformity in the constant of type UTF-8 Encoded data .
  • Class Is there any deleted or additional information in each part of the file and the file itself .
2. Metadata validation

The second stage is semantic analysis of the information described by bytecode , In order to ensure that the information described in it conforms to 《Java language norm 》 The requirements of , The verification points that may be included in this phase are as follows :

  • Does this class have a parent class ( except java.lang.Object outside , All classes should have parents ).
  • Whether the parent class of this class inherits the class that is not allowed to be inherited ( By final Modified class ).
  • If this class is not an abstract class , Whether all the methods required to be implemented in its parent class or interface are implemented .
  • Fields in class 、 Whether the method conflicts with the parent class ( For example, covering the parent class final Field , Or there is a method overload that does not conform to the rules , For example, method parameters are consistent , But the return value type is different ).
  • ……

The main purpose of the second stage is to verify the metadata information of the class , Guarantee that there is no relationship between 《Java language norm 》 Defining conflicting metadata information .

3. Bytecode verification

The third stage is the most complicated stage in the whole verification process , The main purpose is through data flow analysis and control flow analysis , Make sure the program semantics are legal 、 Logical . After the verification of data types in metadata information in the second stage , This stage is about to The method body of the class (Class In the document Code attribute ) Conduct calibration analysis , Ensure that the method of the verified class will not do harm at run time The behavior of virtual machine security , for example :

  • Ensure that the data type and instruction code sequence of the operand stack can work together at any time , For example, it will not appear similar to “ Put a... On the operation stack int Data of type , Press... When using long Type to load into the local variable table ” In this case .
  • Ensure that no jump instruction will jump to a bytecode instruction outside the method body .
  • Ensure that the type conversion in the method body is always valid , For example, you can assign a subclass object to the parent data type , It's safe
    Of , But assign the parent object to the child data type , Even assigning an object to something that has nothing to do with its inheritance 、 A completely irrelevant one data type , It's dangerous and illegal .
4. Symbol reference validation

The last phase of verification occurs when the virtual machine converts symbolic references to direct references , This transformation will take place in the third phase of the connection —— Occurs during the parsing phase . Symbolic reference validation can be seen as outside the class itself ( Various symbols in the constant pool quote ) All kinds of information are checked for matching , Generally speaking, it's , Whether the class is missing or prohibited from accessing some external... On which it depends class 、 Method 、 Fields and other resources . At this stage, the following contents usually need to be verified :

  • Whether the fully qualified name described by string in symbol reference can find the corresponding class .
  • Whether there are methods and fields described by field descriptors and simple names that match the methods in the specified class .
  • Classes in symbolic references 、 Field 、 Method accessibility (private、protected、public、) Whether it can be accessed by the current class .
Get ready Prepare

The preparation phase is formally defined for variables in the class ( That is, static variables , By static Decorated variable ) The stage of allocating memory and setting the initial value of class variables .

About the preparation stage , There are two confusing concepts that need to be emphasized , The first is to allocate memory at this time Only class variables , Not instance variables , Instance variables will be assigned to the Java In the pile .

Zero value of basic data type :

 Insert picture description here

It's mentioned above in “ General situation ” The next initial value is zero , The implication is that there will be some “ A special case ”: If there is... In the field property table of a class field ConstantValue( Constant ) attribute , In the preparation stage, the variable value will be initialized to the initial value specified by the constant attribute , Let's say the class variable above value The definition of :

public static final int value = 123;

That is to say, give attributes value Combined with the final keyword ,value It will be initialized directly to 123.

analysis Resolve

In the parsing phase, the virtual machine replaces the symbolic reference in the constant pool with the direct reference . Parsing actions are mainly for classes or interfaces 、 Field 、 Class method 、 Interface method 、 Method type 、 Method handle and call qualifier 7 Class symbol reference .

Symbol reference It's a set of symbols that describe the goal , It can be any literal amount . Direct reference It's a direct pointer to the target 、 Relative offset or an indirect handle to the target . In the parsing phase, the virtual machine replaces the symbolic reference in the constant pool with the direct reference , That is to get the class or field 、 Method pointer or offset in memory .

initialization Initialization

Class initialization time

  1. Create an instance of a class
  2. Accessing static variables of a class or interface , Or assign a value to the static variable
  3. Calling static methods of a class
  4. Reflection ( such as :Class.forName(“com.atguigu.Test”))
  5. Initializing a subclass of a class
  6. Java The class marked as the startup class when the virtual machine starts
  7. JDK7 Start with dynamic language support :java.lang.invoke.MethodHandle The parsing result of the instance REF_getStatic、REF putStatic、REF_invokeStatic The class corresponding to the handle is not initialized , Then initialize

In addition to the above seven cases , Other uses Java The way of a class is seen as a passive use of a class , Will not cause class initialization , That is, the initialization phase is not executed ( Not invoke clinit() Methods and init() Method )

  • The initialization phase is to execute the initialization method <clinit> () Method process , Is the last step in class loading , This step JVM To actually execute what is defined in the class Java Program code ( Bytecode ).
  • Initialization method <clinit> () Used to initialize class variables , This initialization is the same as the previous preparation (prepare) The initial value assigned to the variable in the stage is different , This initialization is called when we display the value given to the variable, that is, when we manually give the initialization , If we don't give it an initial value manually, we won't call this initialization method .
/** * ClintTest  It is a loader that loads class variables, that is, static variables of classes  */
public class ClintTest {
    
    public static int value = 1;

    public static void main(String[] args) {
    
		
    }
}

<clinit>() Medium bytecode :

0 iconst_1
1 putstatic #2 <java1/ClintTest.value>
4 return

Initialization in a static code block also calls :

public class ClintTest {
    
    public static int value;
    
    static {
    
        value = 123;
    }
}

 Insert picture description here

3、 The instructions in the constructor method are executed in the order in which the statements appear in the source file

But this is what happens :

It looks like assigning a value to a variable before defining a variable

public class ClintTest {
    
    static {
    
        value = 123;
    }

    public static int value;
}

This is because JVM Class variables will be initialized during loading , And then use <clinit> () Assign values to class variables .

4、 The virtual machine must guarantee a class of <clinit>() Method is locked synchronously under multithreading

public class DeadThreadTest {
    
    public static void main(String[] args) {
    
        Runnable r = () -> {
    
            System.out.println(Thread.currentThread().getName() + " Start ");
            DeadThread dead = new DeadThread();
            System.out.println(Thread.currentThread().getName() + " end ");
        };

        Thread t1 = new Thread(r," Threads 1");
        Thread t2 = new Thread(r," Threads 2");

        t1.start();
        t2.start();
    }
}

class DeadThread{
    
    static{
    
        if(true){
    
            System.out.println(Thread.currentThread().getName() + " Initialize the current class ");
            while(true){
    

            }
        }
    }
}

Thread 1 will not release the lock because it falls into an endless loop , So the program will get stuck here .

 Threads 1 Start 
 Threads 2 Start 
 Threads 1 Initialize the current class 

Classification of class loaders

  • JVM Two types of classloaders are supported , It is divided into boot class loader (Bootstrap ClassLoader) And custom class loader (User-Defined ClassLoader).
  • conceptually , Custom class loader generally refers to a class of class loader defined by developers in a program , however Java The virtual machine specification is not so defined , It is All derived from abstract classes ClassLoader Class loaders of are divided into custom class loaders
  • Regardless of the type of class loader , Our most common class loader in programs is always 3 individual :

 Insert picture description here

Although in the figure above, the class loader has Bootstrap、Extension、System and Optional Of , But according to Java Virtual machine specification Extension、System They are all custom class loaders , Because they all inherited ClassLoader abstract class .

BootstrapClassLoader Boot class loader

  • Use C、C++ Realization , Nested in JVM Inside .
  • Used to load Java Core library , For providing JVM The class you need .
  • No inheritance java.lang.ClassLoader, No parent loader .
  • Loading extension classes and application class loaders , And specify them as their parent class loader .
  • For safety reasons ,Bootstrap The boot class loader only loads packages named java、javax、sun Class with equal beginning .
  • stay Java In the program , We can't get , Even if you get it, you can only get null

ExtensionClassLoader Extend the classloader

  • Java Language writing , from sun.misc.Launcher$ExtClassLoader Realization .
  • Derivation and ClassLoader class .
  • The parent loader is the boot loader .
  • from java.ext.dirs Load the class library in the directory specified by the system property , Or from JDK Of the installation directory jre/lib/ext subdirectories ( Extended Directory ) Download the class library . If the user created JAR Put it in this directory , It will also be automatically loaded by the extension class loader .
  • Can be in Java Get... In the program .

APPClassLoader system class loader

  • Java Language writing , from sun.misc.Launcher$AppClassLoader Realization .
  • Derivation and ClassLoader class .
  • The parent loader is the boot loader .
  • User defined classes are usually loaded by this .

User defined class loader

stay Java In daily application development , Class loading is almost done by 3 Class loaders work with each other , When necessary , We can also customize the classloader , To customize how classes are loaded . So why do you need a custom class loader ?

  • Isolation loading class
  • Modify the way the class is loaded
  • Extended load source
  • Prevent source code leakage

How to customize class loader :

  1. Developers can inherit abstract classes java.lang.ClassLoader Kind of the way , Implement your own classloader , To meet some special needs
  2. stay JDK1.2 Before , When customizing class loaders , Always inherit ClassLoader Class and rewrite loadClass() Method , So as to implement the custom class loading class , But in JDK1.2 After that, users are no longer recommended to overwrite loadClass() Method , Instead, it is recommended to write the custom class loading logic in findclass() In the method
  3. When writing custom class loaders , If there are not too complex requirements , Can inherit directly URIClassLoader class , In this way, you can avoid writing by yourself findclass() Method and the way to get the byte stream , Make the custom class loader more concise .

Parent delegate mechanism

principle

Java Virtual machines are right class The document uses Load on demand The way , That is to say, the class will be used only when it is needed class File loading into memory generation class object . And load the class When you file ,Java The virtual machine adopts the mode of parent delegation , That is, leave the request to the parent class , It's a task delegation model .

  1. If a class loader receives a class load request , It doesn't load itself first , Instead, the request is delegated to the loader of the parent class .
  2. If the parent loader still has its parent loader , Then further entrust , Recursion in turn , The request will eventually reach the top-level boot loader .
  3. If the parent loader can complete the class loading task , You're back , If the parent loader cannot complete this load task , Sub loader will try to load by itself , This is it. Parent delegation mode .
  4. The parent loader allocates tasks one layer at a time , If the subclass loader can load , Then load this class , If the load task is assigned to the system class, the loader cannot load this class , Throw an exception .

 Insert picture description here

Code example

give an example 1

We create one under our own project java.lang.String

package java.lang;

public class String {
    
    static {
    
        System.out.println(" Self defined String class ");
    }
}

Testing with a test class :

public class Main {
    
    public static void main(String[] args) {
    
        String str = new String();
        System.out.println("Hello, World!");
    }
}

Output :

Hello, World

Hello, World!

You can see that the content in the static code block is not output , This is because the parental delegation mechanism , Delegate the parent class loader before loading the class , If the parent class also has a parent class loader , Then continue to entrust upward . This is our custom String The full class name of the class is java.lang.String, Finally, it is delegated to the boot class loader to load , So I loaded according to the full class name jdk Native String class .

give an example 2

If in a custom String Class creates a main Methods? ? Or native String There are no methods for classes ?

package java.lang;

public class String {
    
    public static void main(String[] args) {
    
        System.out.println("Hello, World!");
    }
}

Output :

 error :  In the class  java.lang.String  I can't find it in China.  main  Method ,  Please put  main  Method is defined as :
   public static void main(String[] args)
 otherwise  JavaFX  The application class must extend javafx.application.Application

Or because of the parental delegation mechanism , Delegate to boot class loader Bootstrap ClassLoader To load the , But loaded native String There is no such method in class , So loading failed .

give an example 3

We're customizing a java.lang Package, a class that is not in the core package :

package java.lang;

public class Test {
    

}

-------------------------------------------

package java2;

public class Main {
    
    public static void main(String[] args) {
    
        Test test = new Test();
        System.out.println(test);
    }
}

Output :

Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang
	at java.lang.ClassLoader.preDefineClass(ClassLoader.java:655)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:754)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at java2.Main.main(Main.java:5)

This is because there is a protection mechanism , Even if the class name is not repeated , Package names can't be named like that .

Sandbox security mechanism

  1. Customize String Class time : When loading custom String Class will be the first to use the bootstrap loader to load , The bootstrap loader will load first during the loading process jdk The documents that come with you (rt.jar In bag java.lang.String.class), There is no wrong information main Method , It's because the load is rt.jar In bag String class .
  2. This will ensure that you are right java Protection of core source code , This is the sandbox security mechanism .

Add

stay JVM The middle represents two class There are two conditions for whether the object is the same class :

  1. The full class name of the class must always be , Include package name .
  2. Load the ClassLoader(ClassLoader Instance object ) It has to be the same .

JVM You must know whether a type is loaded by the boot loader or the user class loader ; If a type is loaded by a user class loader , that JVM A reference of this class loader will be saved in the method area as part of the type information. When resolving a reference from one type to another ,JVM You need to ensure that these two types of classloaders are the same .

版权声明
本文为[God annoyed dog broke into your blog]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231721278919.html