[architect interview - JVM principle-2] - JVM loading class process

Posted by smarlowe on Sun, 07 Nov 2021 02:21:13 +0100

1: Overall architecture of Java program runtime

 

Java starts the JVM through the latch program, loads the class through the class loader, and first loads the metadata information of the class, including the method instructions compiled by the class. This information is first placed in the Method Area.

The data in the Method area is Runtime Data, and some of these data are instructions. These instructions need to run and must rely on threads. stack and ProgramCounter are required for thread execution. When these two parts are combined to execute the program, heap (heap is required for object initialization) is required. If JNI(java native interface) is called, Native memory is also required

The execution of java bytecode requires an execution engine, which includes a JIT compiler (just   in time) is to execute while compiling, that is, to execute machine code while compiling instructions into machine code. The compiled program will not be compiled for the second time, that is, it will be compiled once and run everywhere.

GC is the garbage collector and java memory allocation tool, that is, the actual manager of the java heap.

Local library interface: any language inevitably calls the local interface. For example, the Java thread is only an Object, and it has no way to execute the program. Only the operating system can execute and call the CPU, including the memory allocation of GC. It also needs memory space from the operating system. The local library interface will call local methods to implement.

2: JVM loading class procedure

 

In Java, a Java class will be compiled into a class file. At compile time, Java classes do not know the actual address of the referenced class, so they can only use symbolic references instead. For example, the org.simple.People class refers to the org.simple.Language class. During compilation, the People class does not know the actual memory address of the Language class, so it can only use the symbol org.simple.Language to represent the address of the Language class.

Difference between loadClass and forName

The class obtained by Classloader.loadClass is unlinked.

The class obtained by Class.forName has been initialized

3: Parent delegation mechanism of ClassLoader

Parents' names are not accurate. In fact, it is father, father's father.

ClassLoader type:

BootStrapClassLoader: loads the core library java. *, written in c + +

ExtClassLoader: loads the extension library javax. * written in Java (jre/lib/ext)

AppClassLoader: the directory where the loader is located. It is written in Java (classpath)

Custom ClassLoader: customized loading, written in Java

Advantages: avoid loading multiple same bytecode objects (Class objects). For example, if A has loaded A Class before, there will be A Class object of this Class. When B is using it, it does not need to create A new Class object of this Class, but looks for the Class object layer by layer from the current ClassLoader to the parent ClassLoader, If A ClassLoader has already loaded this Class object, you do not need to create another Class object of this Class.

4: What is ClassLoader

ClassLoader mainly works in the loading phase of Class loading. Its main function is to obtain Class binary data stream from outside the system.

All classes are loaded by ClassLoader, which is responsible for loading the binary data stream in the Class file into the system, and then handing it to the Java virtual machine for connection, initialization and other operations.

As you can see from the ClassLoader source code, this class is an abstract class.

Parent is also a ClassLoader type, indicating that there are many types of ClassLoader.

An important method is loadclass (string name). Name is the Class name. This method returns an object of Class type. If it is not found, a ClassNotFoundException exception will be thrown.

Custom class loader

openclass.classloader/Tom.java

package openclass.classloader;
public class Tom {
    static {
        //static is executed during initialization
        System.out.println("hello tom");
    }
}

openclass.classloader /MyClassLoader.java

package openclass.classloader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
 
public class MyClassLoader extends ClassLoader {
    private String path;
    private String classLoaderName;
 
    public MyClassLoader(String path, String classLoaderName) {
        this.path = path;
        this.classLoaderName = classLoaderName;
    }
    //Used to find class files
    @Override
    public Class findClass(String name) {
        byte[] b = loadClassData(name);
        return defineClass(name, b, 0, b.length);
    }
    //Used to load class files
    private byte[] loadClassData(String name) {
        name = path + name + ".class";
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            //Read file (tom.class)
            in = new FileInputStream(new File(name));
            out = new ByteArrayOutputStream();
            int i = 0;
            while ((i = in.read()) != -1) {
                out.write(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }
}

openclass.classloader/ClassLoaderChecker.java

package openclass.classloader;
 
public class ClassLoaderChecker {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //The first parameter is the path of the class file. The second parameter is the name of the custom class loader, which can be taken at will.
        MyClassLoader m = new MyClassLoader("D:/workspace/jvmquestion/openclass/classloader/", "myClassLoader");
        Class c = m.loadClass("openclass.classloader.Tom");
        c.newInstance();
    }
}

5: How to break the parental delegation model

There are many scenarios to break the parental delegation mechanism: JDBC, JNDI, Tomcat, etc

Because the parental delegation model was introduced after JDK1.2, and the class loader and abstract class java.lang.ClassLoader already existed in JDK1.0, Java designers have to make some compromises when introducing the parental delegation model in the face of the existing implementation code of user-defined class loader. Before that, the only purpose of users to inherit java.lang.ClassLoader is to This is to rewrite the loadClass() method. This is because the loader's private method loadClassInternal() will be called when the virtual machine loads the class, and the only logic of this method is to call its own loadClass().

If you want to customize the class loader, you need to inherit ClassLoader and override findClass. If you want to not follow the class loading order delegated by both parents, you also need to override loadClass.

Topics: Java Back-end architecture