Because love so insist, because love so wait. Through the long days without drama to play, finally for the spring of life, mutual encouragement!!

1. Class loader

  • (1). This role

    1.ClassLoader is the core component of Java. All classes are loaded by ClassLoader S object instance. Therefore, during the whole loading (loading) stage,ClassLoader can only affect the loading of the class, but cannot change the class linking and initialization behavior through ClassLoader. Whether or not it runs is up to the Execution Engine

    Classloaders first appeared in Java1.0, when they were developed solely for Java applets. Today, however, classloaders shine in OSGI(hot deployment), bytecode encryption and decryption. This is largely due to the fact that the Java virtual machine designers did not consider binding the class loader inside the Jvm when they designed it, which would have the advantage of being more flexible and dynamic in performing class loading operations

  • The explicit and implicit loading of class files refers to the way that the JVM loads class files into memory (the two methods are usually mixed in daily development)

    1. Explicit loading: Refers to loading class objects in code by calling ClassLoader, such as directly using class.forname (name) or this.getClass().getClassLoader().loadClass()

    2. Implicit loading: The code does not call the ClassLoader method to load the class object. Instead, the VM automatically loads the class object into the memory . Such as a new User ()

Class loader classification

Classification (1).

  1. The JVM supports two types of class loaders: Bootstrap ClassLoader and User-defined ClassLoader.

  2. In concept, a custom ClassLoader is a class of class loaders defined by a developer in a program, but the Java Virtual Machine specification does not define it this way. Instead, it classifies all classloaders derived from the abstract ClassLoader as custom classloaders

  3. Regardless of the class loader type, our common class loaders in programs look like this:

All class loaders, except the top-level start class loader, should have their own “parent class” loader

Start (boot) the class loader Bootstrap

This class loading is implemented in C/C++ and is nested within the JVM

It is used to load Java’s core libraries (JAVA_HOME/jre/lib/rt.jar, resource. Jar, or sum.boot.class.path) to provide classes that the JVM itself needs.

For security reasons,Bootstrap only loads classes whose package names start with Java, Javax, and Sun

(4) Does not inherit from java.lang.ClassLoader, no parent loader

Load extension classes and application class loaders and specify them as their parent class loaders

Extend class loader Extension

① Java language written,sum. Music.Launcher$ExtClassLoader implementation

②. Derived from the ClassLoader class, the parent ClassLoader is the launcher ClassLoader

Load the class libraries from the directory specified by the java.ext.dirs system property, or from the JRE /lib/ext subdirectory (extension directory) of the JDK installation directory. If user-created jars are placed in this directory, they will also be automatically loaded by the extended class loader

Application (system) class loader AppClassLoader

Java language, implemented by sum.misc.Launcher$AppClassLoader

②. Derived from the ClassLoader class, the parent ClassLoader is the extension ClassLoader

It is responsible for loading libraries in the path specified by the environment variable classpath or the system property java.class.path

Class loading is the default class loader in the program, generally speaking,Java applications are completed by it to load the classes

⑤. The ClassLoader can be obtained by using the getSystemClassLoader() method of ClassLoader

User-defined class loaders

In Java daily application development, class loading is almost carried out by the above three types of loaders together. If necessary, we can customize the way of class loading by custom classloaders (custom classloaders usually need to inherit from ClassLoader).

② One of the key factors of the vitality and charm of the Java language is that Java developers can customize class loaders to realize the dynamic loading of class libraries, which can be loaded from local JAR packages or remote resources on the network

When customizing a ClassLoader subclass, there are two common methods:

  • Overrides the loadClass() method (not recommended; this method guarantees the class’s parent delegate mechanism)

  • Override the findClass() method –> recommend

    The two methods are essentially the same, after all loadClass() also calls findClass(), but logically it is best not to modify the internal logic of loadClass() directly. The recommended approach is to simply override the loading method of a custom Class in findClass(), specifying the Class name as an argument and returning a reference to the corresponding Class object.

Write a simple custom loader

public class UserClassLoader extends ClassLoader {
    private String rootDir;

    public UserClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    /** * write the logic of the findClass method */
    @Override
    protectedClass<? > findClass(String name)throws ClassNotFoundException {
        // Get the class file byte array of the class
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        } else {
            // Generate the class object directly
            return defineClass(name, classData, 0, classData.length); }}/** * write the logic that takes the class file and converts it to a bytecode stream *@param className * @return* /
    private byte[] getClassData(String className) {
        // Read the bytes of the class file
        String path = classNameToPath(className);
        try {
            InputStream ins = new FileInputStream(path);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            // Read the bytecode of the class file
            while((len = ins.read(buffer)) ! = -1) {
                baos.write(buffer, 0, len);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /** * full path to class files */
    private String classNameToPath(String className) {
        return rootDir + "\ \" + className.replace('. '.'\ \') + ".class";
    }

    public static void main(String[] args) {
        String rootDir = "D:\\code\\workspace_teach\\JVMdachang210416\\chapter02_classload\\src\\";

        try {
            // Create a custom class loader
            UserClassLoader loader1 = new UserClassLoader(rootDir);
            Class clazz1 = loader1.findClass("com.xiaozhi.java3.User");

            // Create a custom class loader 2
            UserClassLoader loader2 = new UserClassLoader(rootDir);
            Class clazz2 = loader2.findClass("com.xiaozhi.java3.User");
            // Clazz1 and clazz2 correspond to different class template structures
            System.out.println(clazz1 == clazz2); 
            System.out.println(clazz1.getClassLoader());
            System.out.println(clazz2.getClassLoader());
            
            Class clazz3 = ClassLoader.getSystemClassLoader().loadClass("com.xiaozhi.java3.User");
            System.out.println(clazz3.getClassLoader());
            System.out.println(clazz1.getClassLoader().getParent());

        } catch(ClassNotFoundException e) { e.printStackTrace(); }}}Copy the code

2. Parent delegation mechanism

①. Working principle

1. If a classloader receives a classload request, it does not load the request itself. Instead, it delegates the request to the parent classloader

2. If the parent class loader also has a parent class loader, then further delegate up, recursively, the request will eventually reach the top level of the start class loader

3. If the parent loader can complete the task of loading the class, it returns successfully. If the parent loader cannot complete the task, the child loader will try to load the class itself

Nature (2).The order in which classes are loaded is:The boot class loader is loaded first. If not, the extension class loader is loaded. If not, the system class loader or a custom class loader is loaded)

(3). Source code analysis (parents delegate mechanism in Java. Lang. This. LoadClass (String, Boolean) in the interface. The logic of this interface is as follows.)

1. Check the current loader’s cache to see if there is a target class.

2. Check whether the parent loader of the current loader is empty. If not, call the parent-loadClass (name, false) interface

3. Otherwise, if the parent class loader of the current loader is empty, the findBootstrapClassOrNull(name) interface is called and the boot class loader is loaded

4. If the load fails through the preceding three paths, call the findClass(Name) interface to load the file. The interface eventually calls the native interface of the defineClass series of the java.lan g.classLoader interface to load the target Java class.

5. Parental delegation models are hidden in steps 2 and 3

④. Advantages of parental delegation mechanism:

1. Avoid reloading classes and ensure that a class is globally unique (there is no need for the child ClassLoader to load the class again when the parent ClassLoader has already loaded the class)

(2) is randomly to tamper with safety protection program, prevent the core API (custom class: Java. Lang. String | Java lang. ShkStart)

(5) Disadvantages of the parent delegate mode (the delegation process to check whether the class is loaded is one-way, although this way is relatively clear from the structure, so that the responsibility of each ClassLoader is very clear, but also brings a problem, that is, the top ClassLoader can not access the classes loaded by the bottom ClassLoader)

Conclusion: Since the Java virtual Machine specification does not explicitly require the parent delegate model to be used for class loaders, the parent delegate model is recommended. In Tomcat, for example, adopted by the class loader delegation model loading mechanism and the traditional parents have certain difference, when the default class loader receives a class load task, first by its load on its own, and when it is loaded fails, will the class loading tasks delegated to its superclass loader for execution, it is also the Servlet specification recommended one Kind of practice

7. Destruction of parental delegation mechanism and examples

1. The first “break” of the parental delegation model actually occurred before the advent of the parental delegation model — in the “ancient” days before JDK 1.2 came out

2. The second damage parents delegate mechanism: the thread context class loader (this) getSystemClassLoader ())

3. The third “break” of the parental delegation model is caused by users’ pursuit of program dynamics. For example: Hot Swap code, Hot Deployment module

3. Sandbox safety mechanism

(1). As shown in the figure, although we define a String in the java.lang package to try to override the String in the core class library, the BootStrap loader will load the String class in the Java core class library due to the parent delegation mechanism The core library has no main method for String< String class = “String” style = “box-sizing: border-box! Important; word-wrap: inherit! ImportantUse the boot class loader firstJar file (Java \lang\String.class), error message indicating that there is no main method because rt.jar is loaded with the String class. So I canThe guarantee of protection of the Java core source code is called sandbox security

③ Function of sandbox safety mechanism:

1. Ensure program security

2. Protect Java native JDK code

Reference video: Silicon Valley JVM complete tutorial, millions of playback, the peak of the entire network (Song Hongkang details Java VIRTUAL machine)

Reference Books: In-depth understanding of the Java VIRTUAL Machine