Class loader

The ClassLoader is used to load the class bytecode into the Java virtual machine. In general, Java virtual machines use Java classes as follows: Java source files are converted to Java bytecode files (.class files) after passing through Javac. The classloader is responsible for reading the Java bytecode and converting it into an instance of the java.lang.Class Class. Each such instance is used to represent a Java class. The actual situation may be more complex, as Java bytecode may be dynamically generated by a tool or downloaded over a network.

Classes and class loaders

Although the class loader is only used to implement the loading action of the class, it plays a role in Java programs far beyond the class loading stage. For any class, its uniqueness in the Java virtual world needs to be established both by the classloader that loads it and by the class itself. In layman’s terms, comparing two classes to be “equal” only makes sense if the two classes have the same classloader. Otherwise, even if the two classes come from the same class file, they must not be equal as long as they are loaded by different classloaders. “Equality” includes the result returned by the equal method, isAssignableFrom(), isInstance(), and the instance keyword on the Class object representing the Class.

Class loader classification:

It is classified into Bootstrap ClassLoader, Extension ClassLoader, Application ClassLoader, and User Defined ClassLoader.

Bootstrap ClassLoader:

This ClassLoader is implemented in C++ and is not a subclass of ClassLoader. JAVA_HOME/jre/lib/rt.jar, or files named rt.jar in the path specified by -xbootclasspath.

Extension ClassLoader:

This loader, implemented by sun.misc.Launcher$ExtClassLoader, is responsible for loading all libraries in the AVA_HOME/lib/ext directory, or in the path specified by the java.ext.dirs system variable.

Application ClassLoader:

This loader is implemented by sun.misc.Launcher$AppClassLoader, which loads the jar and directory corresponding to the classpath. This is usually the default class loader in your program.

User Defined ClassLoader:

The developer inherits the ClassLoader implemented by the ClassLoader abstract class. The ClassLoader developed by the developer can be used to load classes that are not in the classpath (such as jars or binary bytecodes downloaded from the network), and can also perform minor actions such as encryption before loading class files.

Parental delegation model:

This hierarchical relationship between class loaders, as shown in the figure above, is called the parent delegate model for class loaders. The parent delegate model requires that all class loaders have their own parent class loaders, except for the top-level start class loaders. The parent-child relationship between classloaders is typically not implemented as an inherited relationship, but rather uses a combinative relationship to duplicate the code of the parent loader.

The working process of parental delegation: If a classloader receives a classload request, it first does not load the class itself. Instead, it delegates the request to the parent classloader. This is true at every level of classloaders, so all load requests should eventually be sent to the top level of the starting classloader. Only when the parent class loader reports that it cannot complete the load request (the class is not in the scope it manages) will the child loader attempt to load it itself.

One of the obvious benefits of using the parent delegate model to organize relationships between class loaders is that Java classes have a hierarchy of priorities along with their classloaders. For example, java.lang.Object is stored in rt.jar, and whatever class loader is loading the class, So Object is the same class in each class loader environment of the program. Conversely, if there is no parent delegate model and each class loader does it, if the user writes a class named java.lang.Object and places it in the classpath, There may be multiple different Object classes in an application, and the most basic safe behavior in the Java type system cannot be guaranteed.

Class loader SPI:

The java.lang.ClassLoader class provides several key methods:

LoadClass: this method is responsible for loading a class with the specified name. It first looks for the loaded class, if not found; Load from parent ClassLoader[ExtClassLoader]; If it is not loaded, try loading it from the Bootstrap ClassLoader (findBootstrapClassOrNull). Throw an exception ClassNotFoundException and call your own findClass method to load it. Override this method if you want to change the loading order of a class; If the load order is the same, you can override the findClass method to do special processing, such as decryption, fixed path finding, and so on. Throw a ClassNotFoundException when the Class object is not retrieved through the entire Class search.

If the class needs resolve, call resolveClass to link.

FindLoadedClass This method is responsible for finding the loaded class from the cache of the current ClassLoader instance object, calling the native method.

The findClass method throws a ClassNotFoundException directly, so load the corresponding class in a custom way by overriding loadClass or this method.

FindSystemClass This method looks for a class from sun.misc.Launcher$AppClassLoader. If it doesn’t find one, continue looking from BootstrapClassLoader, and return null if it still doesn’t find one

The defineClass method, which is responsible for converting the binary byte stream into a Class object, is important for custom Class loaders. If the binary bytecode format does not conform to the JVM class file format specification, ClassFormatError is raised. If the generated class name is different from the binary bytecode, NoClassDefFoundError is raised; If the loaded class is protected, has a different signature, or the class name is Java. At the beginning, a SecurityException is thrown.

The resolveClass method is responsible for linking the Class object and returns if it has been linked.

Common exceptions:

ClassNotFoundException This is the most common exception. This exception is caused by the fact that the class file was not found while loading the class in the current ClassLoader.

NoClassDefFoundError This exception is raised when the loaded class references another class that does not exist. For example, if A is being loaded and B is stolen from A, B does not exist or the current ClassLoader cannot load B.

LinkageError This exception is more likely to occur in the case of customized ClassLoader. The main reason is that the class has already been loaded in ClassLoader, and repeated loading will cause this exception.

That’s it! Stay tuned for more next time!