The JVM loads classes through the parent delegation model, that is, when a class loader receives a request to load a class, it first delegates the loading task to the parent class loader, recursively, if the parent class loader can complete the class loading task, it returns successfully. Only if the parent class loader is unable to complete the load task, do the load itself.

Class loader

  1. Bootstrap ClassLoader: Classes that are responsible for loading in the JAVA_HOME\lib directory, or in the path specified by the -xbootclasspath parameter, and are recognized by the virtual machine (by filename, such as rt.jar, libraries with incorrect names will not be loaded even if placed in the lib directory). The startup class loader cannot be referenced directly by Java programs.
  2. The Extension ClassLoader is responsible for loading libraries in the JAVA_HOME\jre\lib\ext directory or in the path specified by the java.ext.dirs system variable.
  3. The Application ClassLoader is responsible for loading the class libraries on the user’s classpath.
  4. Implement a custom ClassLoader by inheriting the java.lang.ClassLoader class (essentially overriding the findClass method).

Conclusion: Class loaders and bytecodes are the cornerstones of Java platform independence. For any class, its class loaders and the class itself must be used to establish its uniqueness in the Java Virtual machine.

Advantages of the parent delegation model:

  1. Uniform loading of base classes (the more basic classes are loaded by the higher loader). As with the java.lang.String class, no matter which class loader loads the class, it is ultimately delegated to the launcher class loader, so it is the same class in the various classloader environments of the program.
  2. Improve the security of Java code. For example, if a user defines a java.lang.String class with the same name as the system library, the class will not be loaded because the topmost classloader will load the system java.lang.String class first, not the custom String class, preventing malicious code injection.
  3. You avoid reloading classes, and you also avoid tampering with Java’s core APIS.

Class loading process

The life cycle of a class goes through the following seven phases:

  • Loading stage

    This stage is used to look up the corresponding Class (by Class name) and convert the byte stream of this Class into the data structure of the method area runtime, and then generate a java.lang.class object in memory that represents this Class as an entry point for other data access.

  • Validation phase

This step is intended to verify the security of the bytecode, and is an important part of the JVM’s protection against system crashes that may result from loading unsafe or incorrect bytecode without security verification.

The main actions of verification are as follows:

  1. File format verification includes constant types in the constant pool, whether various parts of the Class file are deleted or appended with other information, etc.
  2. Metadata verification includes parent class correctness verification (checking whether the parent class is modified by final) and abstract class verification, etc.
  3. Bytecode verification, which is the most critical and complex step, is mainly used to verify whether the semantics in the program are legal and logical.
  4. Symbol reference check, which checks the match of various symbol references outside the class itself, such as in the constant pool.
  • Preparation stage

This stage is used to initialize and allocate memory for static variables defined in the class that are allocated to the method area.

The HotSpot VIRTUAL machine was in the method area until JDK 1.7, after which the variable was stored in the Java heap along with the class object.

  • Parsing stage

This stage is used to parse classes, interfaces, fields, and methods, replacing symbolic references with direct references.

The so-called symbol reference refers to a set of symbols to describe the quoted target, the symbol can be any form of literal, as long as it can be used to unambiguously locate the target; A direct reference is a pointer that can point directly to a target, a relative offset, or a handle that can be indirectly located to the target.

Symbolic references differ from direct references in one important way: when symbolic references are used, the referenced target is not necessarily already loaded into memory; When a direct reference is used, the target of the reference must already exist in the vm memory.

  • Initialize the

The initialization phase is when the JVM officially starts executing the Java business code written in the class. At this point, the class loading process is officially complete.

conclusion

As shown in the figure above, the two light green sections represent the life cycle of a class, from the loading of the class through the creation and use of the class instance to the GC unloading and recycling of the class object when it is no longer in use.

Note that classes loaded by the Java VIRTUAL machine’s three built-in class loaders are not unloaded during the lifetime of the virtual machine. Only classes loaded by user-defined class loaders can be unloaded.