The Java class loader is a part of the JVM runtime environment that dynamically loads classes into the virtual machine’s memory. Classes are usually loaded on demand, or lazily loaded. Thanks to the class loader, the Java runtime does not need to know about files and file systems.

Class life cycle

In the Jvm, the life cycle of a class consists of four stages: load, validate, parse, prepare, initialize, use, and destroy.

  • Loading: Load mainly talking about the JVM to use some of the basic resources, as well as our own class to use, through the class loader, loaded into the JVM virtual machine, among them including the jar, class files, etc., and even can be realized through our own custom class loader to load by these two kinds of resources, such as network, database and so on

  • Parsing: The work done inside parsing includes

    • Verify: Verify this firstBytecode fileIs a Java usable file, such as whether it containsmagicAttributes (binary bytecode files can be seen with cafebabe at the beginning) and other information to determine whether the JVM meets the requirements to prevent malicious code from compromising JVM security
    • Allocate memory for class variables that are static and set their initial values.Class variables, like classes, are initialized in heap memory
    • Preparation: Replace all symbolic references in the constant pool with direct references.A symbolic reference is a literal, and a direct reference is an address reference corresponding to all objects or values
  • Initialization: Initialization is the beginning of the actual execution of Java code. Initialization is simply running the class constructor, not all classes are initialized when the JVM starts. There are many initialization opportunities, and it is actually the process of calling a class constructor at different stages

  • Use: This is a simple way to start the call

  • Destruction: When used and no reference is left, it is cleaned up by garbage collection

    Initialization time

    1. When the JVM starts, the main method is the only static initialization method that is actively called
    2. When an object is new, it triggers the class’s initialization constructor call
    3. When a class method is called using a static method, the class’s static constructor is called to initialize the method if the class has not already been initialized
    4. Ditto for static fields
    5. If the interface is modified by default, the class that directly or indirectly implements the interface will be initialized
    6. Initialization of a subclass triggers initialization of the parent class by calling the constructor of the parent class first
    7. The class that reflection calls, it’s going to be initialized, either new or it’s going to have to be static, it’s going to be initialized
    8. When a MethodHandle instance is called for the first time, it initializes the class of the specified method.

    Will not be initialized

    1. If a subclass refers to a static variable of its parent class, it will only trigger initialization of the parent class

    2. Defining an array (static) object does not trigger initialization of the class

    3. During class preparation, class constants are stored in the constant pool, but constants do not trigger class initialization because they are not called by the class like static

    4. Fetching the Class object of a Class by its name does not trigger Class initialization

    5. When loading a Class via class. forName, the initialize argument tells the Jvm whether or not to initialize the Class. The default value is true, and false indicates that the Class is not initialized

    6. The default loadClass method of Classloader does not trigger class initialization, just loading

    Classification of class loaders

    Class loaders are divided into three categories: start class loaders, extend class loaders, and application class loaders

    The details of what each class load is loaded can be obtained directly from the code, you can go to Google or Baidu for details

    Start the class loader (BootstrapClassLoader)

    The startup class loader is defined by C++. During JVM startup, jar packages for basic JDK operations are loaded. The most commonly used rt.jar packages are loaded into the JVM through this

    Extended class loader (ExtClassLoader)

    By default, the JDK loads all jar extensions from the jre/lib/ext/ folder in the JDK working directory. There are some third-party JAR files that can be loaded by placing jars in this directory, as well as many other methods. Such as setting parameters specified, or even manually loading

    Several ways to extend class custom loading

    Put it in JDK lib/ext or -djava.ext.dirs

    2. Java -cp /classpath or class file to the current path

    3. Customize ClassLoader loading

    4, get the ClassLoader of the currently executing class, reflection call addUrl method to add Jar or path (JDK9 invalid).

    Application Classloader

    This is the longest class loader we use to load our own classes. We usually get the class loader of the current class, such as *.class.getClassloader (), which is actually the application class loader. The parent class to which the class loader can be applied is the extension class loader, which can be obtained via getParent. The parent class to which the extension class loader is applied is the launcher class loader, but the launcher class loader is not defined by Java, so we can’t get it

    Custom class loaders

    Of course, we can also customize a loader to extend the class loading method. Java provides a way to implement this by inherits the abstract class ClassLoader. We can extend its loadClass method to implement our own class loading method. Load the class into the virtual machine. Custom class loaders although they both have the same parent class AppClassLoader, they are completely separate, two different containers

    Class loader features

    Parents delegate

    For example, the java.lang.Object class in RT, if we use multiple class loaders to load, will load multiple same classes, parent delegate mechanism, can avoid this problem, only start the class loader, only load once. Ensure global uniqueness

    1. Check to see if the class you want to load has already been loaded

    2. If the parent class exists, let your parent class load it

    3. If the parent fails to load, it is handed over to the AppClassLoader.

    4. If the application class loader fails to load, catch the exception and load it yourself

    Spi mechanism to break parental delegation

    Spi simple words, it is a plug-in loading mechanism, such as a JDBC Driver, rt package defines a Driver interface, is used to extend the database drive the implementation of the plug-in package, but start the class loader to load the Driver interface, simply do not know their own interface is realized what plug-ins and unable to load the plug-in package, So in their own DriverManager. GetConnection method is invoked, only through this thread to get the current thread through the application class loader for the corresponding driver

    Class.forName("com.mysql.jdbc.Driver");
    Connection connection = DriverManager.getConnection("");
    Copy the code
    Ps: Difference between class. forName and ClassLoader in reflection

    Class. ForName will load and initialize the Class

    The ClassLoader will only load, not initialize

    conclusion

    This paper mainly introduces the class loading process and the role and characteristics of the class loader, we through to the class loader to understand more deeply, we can understand the entire JVM starts to run the process of loading a class, you can define our own loader, his way of loading, even we can do it for the entire code modules, the use of its own class loader in isolation, and so on