[Java] Java class loading and class loader

foreword

Java's class loading phase is divided into: loading, linking, and initialization, and the linking process includes: verification, preparation, and resolution.

1. Loading

Load the bytecode of the class into the method area, and internally use the instanceKclass of C++ to describe the Java class

Important fields of instanceKclass:

  • _java_mirror: Java class mirror, which stores the address of the class object, for example, for String, it stores String.class
  • _super: the parent class
  • _methods: the method
  • _constants: the constant pool
  • _class_loader: class loader
  • _vtable: virtual method table
  • _itable: interface method table

insert image description here

2. Links

The linking phase consists of 验证、准备、初始化three parts

verify

Verify that the class conforms to the JVM specification, and perform security checks, for example: check the magic number of the Java file

Prepare

Allocate address space for static variables, set default values

  • Static variable allocation and assignment are two steps, the allocation of space is completed in the preparation phase, and the assignment is completed in the initialization phase;
  • If the static variable is of final type, and the variable type is a basic data type or a string object, it is assigned in the preparation phase;
  • If the static variable is of final type and the variable type is a reference object, it is still assigned in the initialization phase;

analyze

resolves symbolic references in the constant pool to direct references

3. Initialization

Initialize call ()v, that is, execute the constructor of the class, code blocks, etc., and the virtual machine guarantees the thread safety of this class

timing

In a nutshell, class initialization is lazy

  • The class where the main method is located will always be initialized first;
  • The first time you access the static variable or static method of the class, because these variables are not final, they will be assigned during the initialization phase of the class;
  • Subclass initialization will cause initialization of the parent class;
  • The static variable of the parent class of the subclass method will cause the initialization of the parent class;
  • Class.forName;
  • new causes initialization;

does not trigger class initialization

  • The static final static variables (basic types and strings) of the access class will not be initialized, because the assignment of these variables is in the preparation stage;
  • class object.class does not trigger the initialization of the class;
  • Creating an array of this class does not trigger initialization;
  • The loadClass method of the class loader;
  • When parameter 2 of Class.forName is false

4. Class loader

Take JDK8 as an example

name Where to load classes illustrate
Bootstrap ClassLoader JAVA_HOME/jre/lib no direct access
Extension ClassLoader JAVA_HOME/jre/lib/ext Superior is Bootstrap ClassLoader, access is null
Application ClassLoader classpath The superior is Extension ClassLoader
custom class loader custom parent 为 Application ClassLoader

The role of the class loader: to load the binary bytecode of the class

Parental Delegation

The parent delegation mode is a Java class loading mechanism, which defines a hierarchical parent-child relationship, and the parent class loader delegates requests downward until a suitable class loader is found.

  • First, it will check the cache to find out whether the loader has already loaded this class, and if not, go to the parent class loader to find it;
  • If it is not found in the cache, the class loader will be used from top to bottom to create the class;
  • Finally return to this class;
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            // 检查缓存,是否已经加载过这个类
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        // 向上级的累加器中找
                        c = parent.loadClass(name, false);
                    } else {
                        // 向 Bootstrap 类加载器中找
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
            	// 如果缓存没有找到,就去创建
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    // 调用 findClass 去创建类
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

Guess you like

Origin blog.csdn.net/u011397981/article/details/130426900