the principle and implementation of Java Virtual machine class loading (RPM)
First, Introduction
The class load of a Java Virtual machine (JVM) is the process of loading the bytecode contained in the class file into the JVM and making it part of the JVM. The class dynamic loading technology of the JVM can dynamically load or replace some functional modules of the system at runtime, without affecting the normal operation of other functional modules of the system. This article will analyze the class loading system in the JVM, and discuss the principle, implementation and application of class loading in the JVM.
Second, the Java Virtual machine class load implementation and application
2.1 Introduction to the loading process
The so-called load is the process of looking for a class or a binary form of an interface and using that binary form to construct a class object that represents this or that interface, where the name of the class or interface is given. Of course, the name can also be computed, but more commonly, it is constructed by searching the binary form of the source code that was compiled by the compiler.
In Java, the class loader to load a class into a Java virtual machine, to go through three steps to complete: loading, linking and initialization, wherein the link can be divided into the verification, preparation and parsing three steps, in addition to parsing, the other steps are strictly in order to complete, the main work of each step is as follows:
Loading: Finding and importing binary data for classes or interfaces;
Link: Perform the following validation, preparation and resolution steps, where the parsing step is optional;
Checksum: Check the correctness of binary data of imported class or interface;
Prepare: Allocate and initialize storage space for static variables of class;
Parsing: The symbolic reference is converted to a direct reference;
Initialize: Initializes the Java code and static Java code blocks of the static variables of the class.
For specific details and possible errors during class loading and virtual machine startup, see the Java Virtual Machine specification and deep Java virtual machine. As the focus of this article is not discussed here.
2.2 Implementation of the load
The loading of classes in the JVM is implemented by ClassLoader and its subclasses, and Java ClassLoader is an important Java Runtime system component. It is responsible for locating and loading classes of class files at run time.
In Java, ClassLoader is an abstract class, It is in the package Java.lang, it can be said, as long as the understanding of some of the important methods in ClassLoader, combined with the above described in the JVM class loading specific process, the dynamic loading class This technology has a relatively general grasp, these important methods include the following:
The ①loadcass method LoadClass (String name, Boolean resolve) where the name parameter specifies the names of the classes required by the JVM, expressed in package notation, If the Java.lang.object;resolve parameter tells the method whether the class needs to be parsed, class parsing should be considered before initializing the class, not all classes need to be parsed, and if the JVM only needs to know if the class exists or finds a superclass of that class, then no parsing is required. This method is the entry point of the ClassLoader.
②defineclass method This method takes a byte array of the class file and converts it to a class object. A byte array can be data that is loaded from a local file system or network. It analyzes the byte code into the runtime data structure, verifies the validity and so on.
The ③findsystemclass method Findsystemclass method loads files from the local file system. It looks for the class file in the local file system and, if it exists, uses DefineClass to convert the byte array to a class object to convert the file into classes. This is the default mechanism for the JVM to load classes properly when running Java applications.
The ④resolveclass method Resolveclass (Class C) method resolves the loaded class, and if the class has already been parsed, it will not be processed. When the LoadClass method is called, it determines whether to parse by its resolve parameter.
⑤findloadedclass method when the LoadClass method is called to load the class, the Findloadedclass method is called to see if the ClassLoader is loaded into the class, and if it is mounted, the class object is returned, otherwise null is returned. If you forcibly load a class that already exists, a link error will be thrown.
2.3 Application of the load
In general, we need to inherit the abstract class Java.lang.ClassLoader when we use the virtual machine's class load, where the method that must be implemented is loadclass (), and for this method you need to do the following:
(1) Confirm the name of the class;
(2) Check whether the class requested to be loaded has been loaded;
(3) Check whether the class that the request is loaded is a system class;
(4) Attempt to obtain the requested class from the store of the class loader;
(5) Define the requested class in the virtual machine;
(6) To parse the requested class;
(7) Returns the requested class.
All Java virtual machines include a built-in class loader, the built-in class library loader called the root loader (bootstrap ClassLoader). The special point of the root loader is that it can only load classes that are known at design time, so the virtual machine assumes that the classes loaded by the root loader are secure, trustworthy, and run directly without security authentication. When an application needs to load a class that is not known at design time, it must use a user-defined loader (user-defined ClassLoader). Here's an example of how it's applied.
[Java] View plaincopy
Public abstract class Multiclassloader extends classloader{
...
Public synchronized Class LoadClass (String S, Boolean flag) throws classnotfoundexception{
/* Check if class S is already in local memory */
class Class1 = (Class) Classes.get (s);
/* class S already in local memory */
if (class1! = null) return class1;
try/* load class with default ClassLoader */{
Class1 = Super.findsystemclass (s);
return Class1;
}catch (ClassNotFoundException _ex) {
System.out.println (">> not a System class.");
}
/* Get the byte array of class S */
byte abyte0[] = Loadclassbytes (s);
if (abyte0 = = null) throw new ClassNotFoundException ();
/* Convert a class byte array to a class */
Class1 = DefineClass (null, ABYTE0, 0, abyte0.length);
if (Class1 = = null) throw new Classformaterror ();
if (flag) resolveclass (Class1); /* Parse class */
/* Put the newly loaded class into local memory */
Classes.put (S, Class1);
System.out.println (">> returning newly loaded class.");
/* Returns the loaded, parsed class */
return Class1;
}
...
}
}
Third, the Java Virtual Machine class loading principle
As we know earlier, a Java application uses two types of class loaders: the root loader (bootstrap) and the user-defined loader (user-defined).
The root loader is part of the Java Virtual Machine implementation, for example, if a Java virtual machine is implemented with a C program at the top of the operating system that is already present and being used, then the root loader will be part of those C programs. The root loader loads the classes in some default way, including those of the Java API.
During the run, a Java program can install the user-defined class loader. The root loader is an intrinsic part of the virtual machine, and the user-defined class loader is not, it is written in the Java language, is compiled into a class file and then loaded into the virtual machine, and can be instantiated like any other object.
The architecture of the Java class loader is as follows:
Figure 1 Architecture of class loading for Java
The Java class load model is a proxy (delegation) model. When the JVM requires the class loader CL (ClassLoader) to load a class, CL first forwards the class mount request to his parent loader. CL obtains the opportunity to load this class only if the parent loader is not loaded and cannot load the class. Thus, the proxy relationships of all class loaders form a tree-like relationship.
The root of the tree is the root loader of the class (Bootstrap ClassLoader), which is represented as "null" in the JVM. A class loader other than the root loader has and has only one parent loader. When creating a loader, if the parent loader is not explicitly given, the JVM will default the system loader to its parent loader. Java's basic class loader agent structure 2 shows:
Figure 2 Agent architecture for Java class loading
The following is a detailed description of each class loader.
Root (Bootstrap) Loader: The loader does not have a parent loader, it is part of the JVM implementation, and the core code of the run-time library is loaded from Sun.boot.class.path.
Extension (Extension) Loader: The inherited parent loader is the root loader, unlike the root loader that may be associated with the runtime's operating system, which is implemented in plain Java code, which loads code from the Java.ext.dirs (extended directory).
System or Application loader: The loader is an extension loader, and we all know that when installing the JDK, the environment variable (CLASSPATH) is set from Java.class.path (CLASSPATH environment variable) , it is also implemented in plain Java code, and is the default parent loader for the user-defined class loader.
Application (Applet) Loader: A loader is a system loader that loads small application code from a specific directory on a user-specified network.
When designing a class loader, the following two conditions should be met:
For the same class name, the object returned by the class loader should be the same class object
If the class loader CL1 the request to load Class C to the class loader CL2, CL1 and CL2 should return the same class object for the following class or interface: a) s is a direct superclass of C, B) s is a direct hyperlink to C; c) s is the type of the member variable of C; d) S is the member method of C or the parameter type of the builder, and E) S is the return type of the member method of C.
Each class that has been loaded into the JVM implicitly contains information about the class loader that loaded it.
The class method getClassLoader can get the class loader that loads the class. A class loader recognizes classes including its parent loader-aware class and its own loaded class, and the visible class loader class is the superset of its own loaded class. Note that we can get information about the class loader, but the class that has been loaded into the JVM cannot change its class loader.
The loading process of classes in Java is also the process of agent loading. For example, a JVM in a Web browser needs to load a small application testapplet. The JVM invokes a small application loader ACL (applet ClassLoader) to complete the mount.
The ACL first requests its parent loader, i.e. whether the system loader mounts the Testapplet to load this class, because the Testapplet is not in the load path of the system loader, so the system loader does not find this class, and there is no load success.
Then the ACL itself loads the testapplet. The ACL successfully found the Testapplet.class file through the network and imported it into the JVM. During the load process, the JVM discovers that Testappet is inherited from the superclass Java.applet.Applet.
So the JVM calls the ACL again to load the Java.applet.Applet class. The ACL again loads the applet class in the order above, and the ACL finds that his parent loader has loaded the class, so the ACL directly returns the loaded class to the JVM, completing the loading of the applet class. Next, the superclass of the applet class is also treated as such. Finally, Testapplet and all related classes are loaded into the JVM.
Iv. Conclusion
The dynamic loading mechanism of a class is one of the core technologies of the JVM, and it is also a place that is easily overlooked and causes many misunderstandings. This paper introduces the principle, implementation and application of class loading in JVM, especially analyzes the structure of ClassLoader, its usage and how to use custom ClassLoader to load and execute Java class, hoping to give readers a more in-depth understanding of class loading in the JVM.
The principle and implementation of Java Virtual machine class loading (RPM)