当前位置:网站首页>Class 02 loader subsystem

Class 02 loader subsystem

2022-06-25 18:22:00 Name is too tangled

1. Overview of memory structure

Schematic diagram

 Insert picture description here

Detailed drawing ( english )

 Insert picture description here

Detailed drawing ( chinese )

If you write one by yourself Java Virtual machine , What structures should we mainly consider ?

Class loader and execution engine

2. Class loader and class loading process

2.1 The role of the class loader subsystem

 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 )

2.2 Class loader ClassLoader role

 Insert picture description here

  • class file On the local hard drive , It can be understood as a template painted on paper by a designer , In the end, the template is loaded to JVM According to the example of this file n As like as two peas
  • class file Load into JVM in , go by the name of DNA Metadata templates , Put it in the method area
  • stay .class file –> JVM –> Finally, it becomes a metadata template , This process requires a means of transport ( Class loader Class Loader), Play the role of a courier

2.3 Class loading process

Example HelloLoader

public class HelloLoader {
    

    public static void main(String[] args) {
    
        System.out.println(" thank you ClassLoader Load me ....");
        System.out.println(" Your great kindness , I'll report it in my next life !");
    }
}

 Insert picture description here

The whole loading process

 Insert picture description here

2.3.1 load

  1. Get the binary byte stream that defines a class by its fully qualified name
  2. Convert the static storage structure represented by the byte stream into the runtime data structure of the method area
  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

Add : load .class How to file

  • Load directly from the local system
  • Get... Through the Internet , Typical scenario :Web Applet
  • from zip Read in compressed package , Become the future jar、war The basis of format
  • Runtime compute generation , The most used is : Dynamic proxy technique
  • Generated from other files , Typical scenario :JSP application
  • Extract... From a proprietary database .class file , Relatively rare
  • Get... From the encrypted file , Typical defense Class The protection of the file against decompilation

2.3.2 link

 Insert picture description here

2.3.2.1 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

have access to BinaryViewer Check bytecode file , They all begin with CA FE BA BE, Represents being able to be Java Bytecode file recognized by the virtual machine , If an illegal bytecode file appears , Then it will fail the verification

 Insert picture description here

2.3.2.2 Get ready (prepare)

  • by Class variables Allocate memory and set the default initial value of the variable , That's zero
  • There is no use for final Embellished static, because final The default values will be assigned at compile time , The preparation phase explicitly initializes
  • There is no initialization assigned to instance variables , Class variables are assigned in the method area , And instance variables are assigned to along with the object Java In the pile

Example

stay prepare Will a The assignment is 0; stay initial Phase will a The assignment is 1

public class HelloApp {
    
    private static int a = 1;   //prepare:a = 0 ---> initial : a = 1

    public static void main(String[] args) {
    
        System.out.println(a);
    }
}

2.3.2.3 analysis (Resolve)

  • The process of converting a symbolic reference in a constant pool to a direct reference
  • in fact , Parsing is often accompanied by JVM Do not execute... Until initialization is complete
  • Symbol reference is a set of symbols to describe the referenced target . The literal form of symbolic reference is clearly defined in 《java Virtual machine specification 》 Of class In file format . A direct reference is a pointer directly to the target 、 Relative offset or an indirect handle to the target
  • Parsing actions are mainly for classes or interfaces 、 Field 、 Class method 、 Interface method 、 Method type, etc . Corresponds to... In the constant pool CONSTANT Class info、CONSTANT Fieldref info、CONSTANT Methodref info etc.

2.3.3 initialization

  • The initialization phase is the execution of class constructor methods <clinit>() The process of
  • This method does not need to be defined , yes javac The compiler automatically collects the assignment actions of all class variables in the class and the statements in the static code block .【 When our code contains static Variable time , There will be <clinit>() Method ; If the current class does not exist static Variable , Then its bytecode file will not exist <clinit>()
  • The instructions in the constructor method are executed in the order in which the statements appear in the source file
  • <clinit>() Constructor different from class .( relation : The constructor is from the perspective of virtual machine <init>()
  • If the class has a parent class ,JVM Will guarantee the subclass () Before execution , Of the parent class () Execution completed
  • The virtual machine must guarantee a class of () Method is locked synchronously under multithreading 【 Ensure that the class is loaded only once

example :1:<clinit>() Method

public class StaticTest {
    
    private static int num=1;

    static {
    
        num = 2;
        number = 20;
        System.out.println(num);
        //System.out.println(number);//  Report errors : Illegal forward quotation 
    }

    private static int number = 10;//linking Of perpare Stage :number = 0 --> initial:20-->10

    public static void main(String[] args) {
    
        System.out.println(num);// 2
        System.out.println(number);//10
    }
}

 Insert picture description here

Example 2: The constructor is from the perspective of virtual machine <init>()

public class ClinitTest {
    
    //  After any class is declared , There is at least one class constructor inside 
    private int a = 1;
    private static int c = 3;

    public static void main(String[] args) {
    
        int b = 2;
    }

    public ClinitTest(){
    
        a = 10;
        int d = 20;
    }
}

 Insert picture description here

Example 3: If the class has a parent class ,JVM Will guarantee the subclass <clinit>() Before execution , Of the parent class <clinit>() Execution completed
Execute the process :

  1. perform main( ) Method needs to load ClinitTest1 class
  2. obtain Son.B Static variables , Need to load Son class
  3. Son The parent of a class is Father class , So it needs to be executed first Father Class loading , Re execution Son Class loading
public class ClinitTest1 {
    
    static class Father{
    
        public static int A = 1;
        static {
    
            A=2;
        }
    }

    static class Son extends Father{
    
        public static int B = A;
    }

    public static void main(String[] args) {
    
        //  load Father Class is loaded next Son class 
        System.out.println(Son.B);//2
    }
}

Example 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 runnable = ()->{
    
            System.out.println(Thread.currentThread().getName()+" Start ");
            DeadThread deadThread = new DeadThread();
            System.out.println(Thread.currentThread().getName()+" end ");
        };

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

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

}

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

            }
        }
    }

result :
 Insert picture description here

3. Classloader classification

  • JVM Two types of classloaders are supported . Respectively Boot class loader (Bootstrap ClassLoader) and Custom class loaders (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's going to be All derived from abstract classes ClassLoader Class loaders of are divided into custom class loaders 【ExtClassloader and AppClassLoader All indirectly inherited ClassLoader, Belongs to the custom loader 】
  • Regardless of the type of class loader , Our most common class loader in programs is always 3 individual , As shown below
     Insert picture description here  Insert picture description here
public class ClassLoaderTest {
    
    public static void main(String[] args) {
    
        //  Get system classloader 
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);//[email protected]

        //  Get the top : Extend the classloader 
        ClassLoader extClassLoader = systemClassLoader.getParent();
        System.out.println(extClassLoader);//[email protected]

        //  Get the top : Could not get boot class loader 
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println(bootstrapClassLoader);//null

        //  For user-defined classes : By default, the system class loader is used for loading 
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader);//[email protected]

        // String Class is loaded using the bootstrap class loader --->Java The core libraries of are loaded using the bootstrap class loader 
        ClassLoader classLoader1 = String.class.getClassLoader();
        System.out.println(classLoader1);//null
    }
}
  • Get boot class loader , But the obtained value is null, This doesn't mean that the bootloader doesn't exist , Because the boot class loader is made up of C/C++ Language consists of , So we can't get
  • The values of the system class loader obtained twice are the same , This shows that the system class loader is globally unique

3.1 The loader of the virtual machine

3.1.1 Start class loader ( Boot class loader ,Bootstrap ClassLoader)

  • This class loads using C/C++ The realization of language , Nested in JVM Inside
  • It's used to load Java The core of the library (JAVA_HOME / jre / lib / rt.jar、resources.jar or sun.boot.class.path The content of the path ), For providing JVM The class you need
  • Not inherited from java.lang.ClassLoader, No parent loader
  • Loading extension classes and application class loaders , And as their parent class loader
  • For safety reasons ,Bootstrap Start class loader Only the package name is loaded java、javax、sun Class with equal beginning

3.1.2 Extend the classloader (Extension ClassLoader)

  • Java Language writing , from sun.misc.Launcher$ExtClassLoader Realization
  • Derive from 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

3.1.3 Application class loader ( system class loader ,AppClassLoader)

  • Java Language writing , from sun.misc.LaunchersAppClassLoader Realization
  • Derive from ClassLoader class
  • The parent class loader is the extension class loader
  • It's responsible for loading environment variables classpath or System attribute java.class.path Specify the class library under the path
  • This class loader is the default class loader in the program , Generally speaking ,Java The applied classes are loaded by it
  • adopt classLoader.getSystemclassLoader( ) Method to get the class loader

Code

public class ClassLoaderTest1 {
    
    public static void main(String[] args) {
    
        System.out.println("********** Start class loader **********");
        URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
        for (URL urL : urLs) {
    
            System.out.println(urL.toExternalForm());
        }
        //  Select any class from the above path , Take a look at its classloader : Start class loader 
        ClassLoader classLoader = Provider.class.getClassLoader();
        System.out.println(classLoader);//null

        System.out.println("********** Extend the classloader **********");
        String dirs = System.getProperty("java.ext.dirs");
        System.out.println(dirs);
        for(String path:dirs.split(";")){
    
            System.out.println(path);
        }
        //  Select any class from the above path , Take a look at its classloader : Extend the classloader 
        ClassLoader classLoader1 = CurveDB.class.getClassLoader();
        System.out.println(classLoader1);
    }
}

result

 Insert picture description here

3.2 User defined 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 leaks

Implementation steps of custom 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 , Sure Direct inheritance 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
public class CustomClassLoader extends ClassLoader {
    
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
    

        try {
    
            byte[] result = getClassFromCustomPath(name);
            if (result == null) {
    
                throw new FileNotFoundException();
            } else {
    
                return defineClass(name, result, 0, result.length);
            }
        } catch (FileNotFoundException e) {
    
            e.printStackTrace();
        }

        throw new ClassNotFoundException(name);
    }

    private byte[] getClassFromCustomPath(String name) {
    
        // Load the specified class from the custom path : Details 
        // If the bytecode file of the specified path is encrypted , You need to decrypt in this method .
        return null;
    }

    public static void main(String[] args) {
    
        CustomClassLoader customClassLoader = new CustomClassLoader();
        try {
    
            Class<?> clazz = Class.forName("One", true, customClassLoader);
            Object obj = clazz.newInstance();
            System.out.println(obj.getClass().getClassLoader());
        } catch (Exception e) {
    
            e.printStackTrace();
        }
    }
}

4. ClassLoader Instructions for use

4.1 About ClassLoader

ClassLoader class , It's an abstract class , All subsequent classloaders are inherited from ClassLoader( Does not include boot loader )
【 None of these methods is abstract 】
 Insert picture description here

sun.misc.Launcher It's a java Entry application of virtual machine

 Insert picture description here

4.2 obtain ClassLoader Way

 Insert picture description here

public class ClassLoaderTest2 {
    
    public static void main(String[] args) {
    
        try {
    
            //  Mode one : Get the... Of the current class ClassLoader
            ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();
            System.out.println(classLoader);//null

            //  Mode two : Gets the current thread's ClassLoader
            ClassLoader classLoader1 = Thread.currentThread().getContextClassLoader();
            System.out.println(classLoader1);//[email protected]

            //  Mode three : Get the... Of the current system ClassLoader
            ClassLoader classLoader2 = ClassLoader.getSystemClassLoader();
            ClassLoader classLoader3 = classLoader2.getParent();
            System.out.println(classLoader2);//[email protected]
            System.out.println(classLoader3);//[email protected]
        } catch (Exception e){
    
            e.printStackTrace();
        }
    }
}

5. Parent delegate mechanism 【 The interview often asks 】

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 The file is loaded into memory to generate class object . And load the class When you file ,Java The virtual machine uses Parent delegation mode , That is, leave the request to the parent class , It's a task delegation model

5.1 working principle

  1. If a class loader receives a class load request , It doesn't load itself first , It is Delegate this request to the loader of the parent class To carry out ;
  2. If the parent loader still has its parent loader , Then further entrust , One recursion , The request will eventually reach the top-level boot class loader ;
  3. If the parent loader can complete the class loading task , You're back . If the parent loader cannot complete this load task , The subclass loader will try to load itself , This is the parent delegation model .
     Insert picture description here

5.2 Examples of parental appointment mechanism

Example 1: Self defined String class

public class String {
    

    static {
    
        System.out.println(" I'm custom String Static code block of class ");
    }

    // error :  In the class  java.lang.String  I can't find it in China.  main  Method 
    public static void main(String[] args) {
    
        System.out.println("hello,String");
    }

}

reason : load String Class will be thrown up , Finally, it is loaded by the boot class loader , But in the boot class loader String Class does not main Method , So there's an error

Example 2

SPI The interface is loaded by the boot class loader , The specific implementation class of the interface is loaded by the thread context class loader , The thread context class loader is the system class loader , So when we load , Parents will be assigned first , Load... In the boot class loader SPI Core class , Then load SPI Interface , Finally, in reverse delegation , Implement the class through the system class loader jdbc.jar Loading
 Insert picture description here

5.3 advantage

  • Avoid duplicate loading of classes
  • Protect program security , Prevention core API Be tampered with at will
    • Custom class :java.lang.String There is no call
    • Custom class :java.lang.ShkStart( Report errors : Block creation java.lang Initial class )
       Insert picture description here

5.4 Sandbox security mechanism

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 . This will ensure that you are right java Protection of core source code , This is it. Sandbox security mechanism .

6. other

6.1 Whether two Class Whether the objects are the same

  • stay JVM The middle represents two class There are two necessary conditions for an object to be the same class :
    • The complete class name of a class must be consistent , Include package name
    • Load the ClassLoader( finger ClassLoader Instance object ) It has to be the same
  • let me put it another way , stay JVM in , Even if these two class objects (class object ) From the same source Class file , Loaded by the same virtual machine , But just load their ClassLoader Instance objects are different , Then the two class objects are not equal

6.2 Reference to classloader

  • 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 to the class loader is 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

6.3 Active and passive use of class

Java The way the program uses classes is divided into : Active use and Passive use

  • Active use , There are seven situations :
    • Create an instance of a class
    • Accessing static variables of a class or interface , Or assign a value to the static variable
    • Calling static methods of a class
    • Reflection ( such as :Class.forName(“cn.sxt.Test”) )
    • Initializing a subclass of a class
    • Java The class marked as the startup class when the virtual machine starts
    • DK7 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 class is regarded as the of class Passive use , all Does not cause class initialization 【 The initialization phase will not be called <clinit>() Method
  • The difference between active and passive use depends on whether the initialization phase is executed
原网站

版权声明
本文为[Name is too tangled]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202190531522467.html