JVM-like loading and class loader ClassLoader

The general process of a class from loading to an object in new


Want to know one by one written category, how these simple little lives are forced to operate? How to be consumed by illegal institutions? Let’s take a look. [This article is a blend of various blogs and resource output for reference, Including some of the fields and pictures are not my original output, just for recording and sharing]

What is class loading?

Java code -> bytecode file -> JVM. The process of reading the specified class file into the memory by the JVM and running the Java program in the class file is called class loading; conversely, the process of removing the runtime data of a certain class file from the JVM , It is called the unloading of the class.

Definition: The virtual machine loads the data describing the class from the Class file into the memory , verifies the data, converts, analyzes and initializes, and finally forms a java type that can be directly used by the virtual machine. This is the class loading mechanism of the virtual machine

Timing of class loading (when will the class be loaded?):

When to start loading, the virtual machine specification does not have mandatory constraints. For most other stages, there is no specification of when to start the virtual machine specification. These are all left to the specific implementation of the virtual machine. So different virtual machines may start at different times. However, for initialization, it is strictly stipulated that there are only four cases where the class must be "initialized" ( loading, verification, and preparation naturally need to be completed before initialization ):
1. Encounter the four instructions of new, getstatic, putstatic and invokestatic If the corresponding class is not initialized, the corresponding class must be initialized first. These four instructions correspond to the scenes in our java code, respectively, when the new keyword instantiates an object; reads or sets a static field of a class (read is modified by final, and the result has been put into the constant pool in the compiler Except for static fields); when calling static methods of the class.
2. When using the java.lang.reflect package method to make a reflection call to the class.
3. When initializing a class, it is found that its parent class has not yet been initialized, and its parent class must be initialized first.
4. When the virtual machine starts to start, the user needs to specify a main class, and the virtual machine first executes the initialization of this main class.
The original author is suspicious: The virtual machine specification uses only this very strong qualifier. These four scenarios are called active quoting, and other quoting methods are called passive quoting. Does this mean that references in other ways are not allowed to trigger initialization? Doubtful.

Timing of Class Unloading【Extended Knowledge】

The unloading of classes is related to the garbage collection algorithm used. In CMS, there are two methods to unload unnecessary classes. One is to wait until the Metaspace is full to trigger FGC, and the other is to use the concurrent collection algorithm with CMS. The same way, but the threshold for the meta space and the threshold for triggering CMS concurrent collection are independent. More specific can refer to the previous article: CMS study notes. Here, we only need to remember that the unloading of a class in the JVM must meet the following three conditions:
1. All instance objects of this class have been recycled;
2. The class loader object of this class has been recycled;
3 The java.lang.Class object corresponding to this class is not referenced anywhere, and the methods of this class cannot be accessed through reflection anywhere.

The process of class loading?

A process of class loading: Java source programs (.java files) are converted into Java byte codes (.class files) after being compiled by a Java compiler. The class loader is responsible for reading the Java byte code and converting it into an instance of the java.lang.Class class. Each such instance is used to represent a Java class. An object of this class can be created through the newInstance() method of this instance. The actual situation may be more complicated. For example, Java byte codes may be dynamically generated through tools or downloaded through the network.
Example diagram:
Insert picture description hereWe expand the scene to connect to the jvm memory model. Looking at the overall situation, we have to understand the flow of things from beginning to end, and we can clearly feel the interaction, function and positioning between each.Insert picture description here

Just talked about the process of loading a class. Next, let's clarify the process of loading a project:

Project running process: A number of java files are compiled and packaged to generate a runnable jar package. Finally, the java command runs the main function startup program of a main class . Here , the main class needs to be loaded into the JVM through the class loader . If the main class uses other classes during its operation, these classes will be loaded gradually. Note that the classes in the jar package are not loaded all at once, they are loaded only when they are used .
Picture aboveInsert picture description here

The specific process of class loader loading class


The whole process from class loading to use is as follows: Loading >> Verification >> Preparation >> Analysis >> Initialization >> Use >> Uninstall

The specific explanation is in this link: The jvm class loading process is fine-tuned and explained (personal blow)
above:Insert picture description here

Step analysis [shallow version]:
Load:
1 Obtain the binary byte stream that defines this class through the fully qualified name of a class.
2. Import the static storage structure represented by this binary byte stream as the runtime data structure of the method area.
3. Generate a java.lang.Class object in the java heap to represent this class as the entry for these data in the method area.
After the loading phase is completed, the binary byte stream is stored in the square area according to the format required by the virtual machine

Overview: Find and read bytecode files on the hard disk through IO, and load them when the class is used, such as calling the main() method of the class, the new object, etc.

Personally think that loading the strongest summary and thoughts

In a nutshell, the loading phase is to load the binary byte stream of the class into the method area and set up an entry to access them. The Java virtual machine specification has no specific requirements for these three points. It only says to obtain the "binary byte stream" through the "fully qualified name of the class", but does not say how to obtain it and where to obtain it. It is equivalent to only one interface is defined, and the specific implementation can be played by the implementation of the virtual machine. The virtual machine design team set up a fairly developed and broad stage during the loading phase. In the development process of java, many important java technologies are built on this basis, for example:
1. Read from ZIP package, read from JAR, EAR, WAR format.
2. Obtained from the Internet. A typical reference for this scenario is Applet.
3. Automatically generated at runtime. Dynamic proxy technology is most used in this scenario. In java.lang.reflect.proxy, ProxyGenerator.generateProxyClass is used to generate a binary byte stream of the proxy class of *Proxy for a specific interface.
4. Generated from other files, such as jsp.
5. Read from the database.
Compared with other stages of the class loading process, the loading phase (to be precise, the process of obtaining the binary byte stream of the class in the loading phase) is the most controllable process during the development period, because the loading phase can use system-defined The class loader is used for loading, and the class loader can also be customized to control the loading method of the binary byte stream.
There is no specific specification for the data storage format virtual machine specification in the method area, which is defined by the implementation of the virtual machine.

-connection

  • Verification: to ensure the correctness of the loaded class

  • Preparation: Allocate memory for static variables of the class and initialize them to default values

  • Resolution: Replace symbolic references with direct references. At this stage, some static methods (symbol references, such as the main() method) will be replaced with pointers or handles to the memory where the data is stored (direct references). This is the so-called static linking process (Completed during class loading), dynamic linking is done during the running of the program, replacing symbol references with direct references

Initialization: initialize the static variables of the class to the specified value, and execute the static code block

General overview: The virtual machine loads the data describing the class from the Class file into the memory , and performs verification, conversion, analysis, and initialization of the data, and finally forms a java type that can be directly used by the virtual machine. The process of class loading and connection is completed during runtime .

The relationship between class and class loader


So you have thought about how to determine the uniqueness of a class in JVM? Is it true that the fully qualified name of a class can be uniquely determined? If a person has the same name but is not born to a mother, they are The same person?

For any class, you need to load its class loader and the class itself to determine the uniqueness of this class in the Java virtual machine. Each class loader has an independent class name space . In other words, if you compare whether two classes are the same class, in addition to comparing whether the fully qualified names of the two classes themselves are the same, you must also compare whether the two classes are loaded by the same class loader. Even if the same class file is loaded into the same virtual machine twice, if it is loaded by two different class loaders, the two classes are still not the same class.

Not much bb code to serve

package com.csdn.demo_ds.jvm;

/**
 * @author Administrator
 * @ClassName ClassLoaderTest
 * @Description
 * @date 2020-11-11 11:50
 */


import java.io.IOException;
import java.io.InputStream;

public class ClassLoaderTest {
    
    
    public static void main(String[] args) throws Exception{
    
    
        ClassLoader loader=new ClassLoader() {
    
    
            @Override
            public Class<?> loadClass(String name)throws ClassNotFoundException{
    
    
                try{
    
    
                    //组装成 ClassLoaderTest.class
                    String filename=name.substring(name.lastIndexOf(".")+1)+".class";
                    //getClass()得到类  getResourceAsStream(filename)通过文件名得到类信息放入到inputsrteam中去
                    InputStream is=getClass().getResourceAsStream(filename);
                    if(is==null){
    
    
                        //双亲加载机制
                        return super.loadClass(name);
                    }

                    byte[] b=new byte[is.available()];
                    is.read(b);
                    //加载类
                    return defineClass(name,b,0,b.length);
                }catch(IOException e){
    
    
                    throw new ClassNotFoundException(name);
                }
            }
        };
        Object obj=loader.loadClass("com.csdn.demo_ds.jvm.ClassLoaderTest").newInstance();
        System.out.println(obj.getClass());//类名
        System.out.println(obj.getClass().getClassLoader());//类加载器
        System.out.println(ClassLoaderTest.class.getClassLoader());//应用类加载器
        System.out.println(obj instanceof com.csdn.demo_ds.jvm.ClassLoaderTest);
    }
}

Class loader and parent delegation mechanism


There are the following types of java class loader :
1. Start the class loader :

Responsible for loading the core class libraries in the lib directory of the JRE that support JVM operation, such as rt.jar, charsets.jar, etc. In other words, responsible for storing them in the <JAVA_HOME>\lib directory or specified by the -Xbootclasspath parameter In the path, and the class library recognized by the virtual machine is loaded into the virtual machine's memory. The startup class loader cannot be directly referenced by the Java program. When the user writes a custom class loader, if the loading request needs to be delegated to the boot class loader, then directly use null instead.

2. Extended class loader :

Responsible for loading the JAR class package in the ext extension directory under the lib directory of the JRE that supports the JVM operation. This loader is implemented by sun.misc.Launcher$ExtClassLoader and is responsible for loading the <JAVA_HOME>\lib\ext directory, or is Developers can directly use the extended class loader for all class libraries in the path specified by the java.ext.dirs system variable.

3. Application class loader :

Responsible for loading class packages under the ClassPath path, mainly loading those classes you wrote yourself. This class loader is implemented by sun.misc.Launcher$AppClassLoader. Since this class loader is the return value of the getSystemClassLoader method in ClassLoader, it is also called the system class loader. It is responsible for loading the class library specified on the user's classpath. Developers can directly use this class loader. If the application has not customized its own class loader, this is generally the default class loader in the program.

4. Custom loader : responsible for loading class packages under user-defined paths

The parent delegation mechanism is above:
Insert picture description here
Description:

There is actually a parent delegation mechanism for class loading. When loading a certain class, it will first entrust the parent loader to find the target class, and then entrust the upper parent loader to load if it cannot find the parent loader. If all parent loader are in their own loading class path If the target class is not found, it will find and load the target class in its own class loading path. For example, our Math class will first find the application class loader to load, the application class loader will first entrust the extension class loader to load, the extension class loader then entrusts the startup class loader, the top-level startup class loader is in its own After searching in the class loading path for a long time and failing to find the Math class, it returns to the request to load the Math class, and the extended class loader loads itself after receiving the reply. After searching in the class loading path for a long time, the Math class is not found. Back down to the loading request of the Math class to the application class loader, the application class loader then looks for the Math class in its own class loading path, and loads it itself when it finds it. . The parent delegation mechanism is simpler: find the father to load it first, and then let the son load it.

So why is there a parent loading mechanism?

1. Sandbox security mechanism: the java.lang.String.class class written by yourself will not be loaded, so that you can prevent the core API library from being tampered with at will
. 2. Avoid repeated loading of the class: when the father has already loaded the class, There is no need to load the child ClassLoader again to ensure the uniqueness of the loaded class

If there is no such mechanism. In our minds, all Java applications need to reference the java.lang.Object class at least, which means that the java.lang.Object class needs to be loaded into the Java virtual machine at runtime. If this loading process is completed by the Java application's own class loader, there are likely to be multiple versions of java.lang.Object classes, and these classes are not compatible. Through the parental delegation model, the loading of the classes of the Java core library is uniformly completed by the startup class loader, which ensures that Java applications use the same version of the Java core library classes and are compatible with each other.

Different class loaders create additional namespaces for classes of the same name. Classes with the same name can be stored in the Java virtual machine, just use a different class loader to load them. The classes loaded by different class loaders are incompatible, which is equivalent to creating a separate Java class space inside the Java virtual machine

For specific in-depth discussion about parental appointment, refer to the blog of this god-man: Academic Research Great God

Guess you like

Origin blog.csdn.net/f_a_ker/article/details/109614984