First, the class loading mechanism hierarchy
Each “. Java “extension class file that is written contains the program logic that needs to be executed. These”. Java “files are compiled by the Java compiler into files with the extension name”. The.class file contains converted Java code and vm instructions. When a class needs to be used, the VM loads its. Class file, creates a corresponding class object, and loads the class file into the VM memory. As follows:
The Jvm executes the class file
Step 1: Class loading mechanism
The class loader is required to load the class file bytecode content into memory, convert the static data into runtime data structures in the method area, and generate a java.lang. class object representing the class in the heap as an access point to the method area class data.
When the system is running, the class loader transfers the binary data of the. Class file from the external memory (such as cd-rom, hard disk) to the memory, and the CPU reads the instructions and data from the memory for calculation, and stores the calculation results in the memory. Within the process ACTS as a “setter” role, popular, if there is no memory, class loader from the external storage device call. The class file binary data directly to the CPU, due to the processing speed of CPU is far greater than the speed of data transfer into, easy to cause disconnection between data, so we need to memory buffer role.
After the class loads the.Class file into the method area at runtime, it creates a java.lang. class object in the heap to encapsulate the data structure of the class in the method area. The class object is created during the class loading process. Class Class constructors are private and can only be created by the JVM. The Class object is therefore the entry point for reflection, and is used to obtain the concrete data structure in the.class file associated with the target Class.The end product of Class loading is a Class object in the heap (not the target Class object) that encapsulates the Class’s data structure in the method area and provides the user with an interface to access the method area data structure, the Java reflected interface.
Step 2. Connection process
The process of merging the binaries of Java classes into the JVM’s running state
Validation: To ensure that the loaded class information complies with the JVM specification and that there are no security issues
Preparation: The stage of formally allocating memory and setting initial values for class variables (static variables), which will be allocated in the method area
Resolution: symbolic references to the virtual machine constant pool are replaced by byte-reference procedures
Step 3. Initialize
The initialization phase is the process of executing the class constructor () method. Class constructor () methods are generated by the compiler automatically storing the assignment of all class variables in a class with statements in a static block, which is executed from the top down.
When initializing a class, if the parent class has not been initialized, the initialization of the parent class must be triggered first
The virtual machine ensures that a class’s () methods are properly locked and synchronized in a multithreaded environment. When scoping a Java class’s static domain, only classes that truly represent that domain are initialized
Second, the class loader hierarchy
Bootstrap the class loader
Extension class loader
System (-) classloader
1. Bootstrap the class loader
The startup class loader loads classes that the JVM needs. This class loading is implemented in C++ and is part of the virtual machine itself. It is responsible for loading the core libraries in /lib or jar packages in the path specified by the -xbootclasspath parameter into memory. Notice The VM loads jar packages based on the file name, such as rt.jar. If the file name is not recognized by the VM, throwing the JAR package to the lib directory is useless. For security reasons, Bootstrap starts the class loader to load only classes whose package names start with Java, Javax, and Sun.
Extension class loader
The extended class loader is the Sun.misc.Launcher$ExtClassLoader class implemented by Sun corporation (acquired by Oracle). Implemented in the Java language, it is a static inner class of the Launcher. It is responsible for loading libraries in the /lib/ext directory or in the bitpath specified by the system variable -djava.ext. dir. Developers can use the standard extension classloader directly.
3. System class loader
Also called application loader, it refers to Sun’s implementation of Sun.misc.Launcher$AppClassLoader. Java-classpath or -d java.class.path specifies the classpath path for the class libraries. Developers can use the system classloader directly, which is the default class loader. The class loader can be obtained by using the ClassLoader#getSystemClassLoader() method.
In everyday Java application development, class loading is almost carried out by the above three types of loaders. If necessary, we can also customize the class loaders. It is important to note that the Java virtual machine is used to load class files on demand. That is, when a class is needed, its class file is loaded into memory to generate a class object, and when a class file is loaded, the Java virtual machine uses parent delegate mode to delegate requests to the parent class. It is a task delegate mode, which we will learn more about next.
3.1. Understand the parental delegation pattern
At the code level, let’s take a look at the implementation of several class loaders defined in Java and their parent delegate pattern, with the following class diagram relationship
Parents delegation model is introduced after the Java 1.2, its working principle is that if a class loader received class loading request, it will not go to loading, but the request entrusted to the parent class loader for execution, if the parent class loader has its parent class loader, further upward, in turn, recursion, Request will eventually reach the top to start the class loader, if the parent class loader finish class loading can be successfully returns, if the parent class loader cannot complete this task load, child loader will try to load, it is parents delegate pattern, namely every son is lazy, every time just throw it to the father to do, until my father said it also I can do, His son to find a way to complete, this is the legendary strength pit dad ah? So what’s the use of this model?
3.1 advantages of parental delegation mode
The advantage of parental delegation is that Java classes have a hierarchy of priorities with their classloaders. This hierarchy avoids reloading classes, and there is no need for the child ClassLoader to load the class again when the parent has already loaded the class. Second, for security reasons, defined types in the Java core API will not be arbitrarily replaced. Suppose that a class named java.lang.Integer is passed over the network through the parent delegate mode to the initiator class loader, and the initiator class loader finds the class with this name in the core Java API and finds that the class has been loaded. Instead of reloading java.lang.Integer passed by the network, integer.class is returned, which prevents the core API library from being tampered with. You might be thinking, what if we had a custom class named java.lang.SingleInterge in the classpath path (the class is made up)? The class does not exist in java.lang, and is passed to the startup class loader through the parent delegate mode. Since there is no class in the parent class loader path, it will not be loaded, and the reverse delegate to the subclass loader will be loaded, and eventually the class will be loaded through the system class loader. However, this is not allowed because java.lang is the core API package and requires access rights. Forced loading will result in the following exception
java.lang.SecurityException: Prohibited package name: java.lang
So it can’t be loaded successfully anyway.
Relationships between class loaders
Let’s take a closer look at the relationships between class loaders (rather than inheritance relationships), which can be divided into four main points
- Start class loader, implemented by C++, no parent class.
- ExtClassLoader (ExtClassLoader), implemented by Java language, the parent class loader is null
- System class loader (AppClassLoader), implemented by the Java language, the parent class loader for ExtClassLoader
- Custom class loader. The parent class loader must be AppClassLoader.
1. Common methods of class loaders
loadClass(String)
This method loads binary types with specified names (including package names). This method is not recommended to be overridden after JDK1.2, but users can call this method directly. The loadClass() method is implemented by the ClassLoader class itself. LoadClass (String name, Boolean resolve) loadClass(String name, Boolean resolve) is an overloaded method.
As the loadClass method shows, when a class load request comes in, it looks for the class object in the cache, returns it if it exists, passes it to the class’s parent loader if it doesn’t exist, passes it to the top start class loader if it doesn’t have a parent, and finally, if it doesn’t find one, The findClass() method is used to load it (more on findClass() later). If you do not want to redefine the rules for loading classes, and do not have complex logic, you just want to load your specified classes at runtime, then you can use this.getClass().getClassloder.loadClass (“className”). You can call the loadClass method of the ClassLoader directly to get the class object.
findClass(String)
Before JDK1.2, it was common to inherit the ClassLoader class and rewrite the loadClass method to implement custom class loading classes. However, after JDK1.2, it is no longer recommended that users override the loadClass() method. FindClass () is called in the loadClass() method. If the parent loadClass() method fails to load, the findClass() method is called in the loadClass() method. It calls its own findClass() method to complete the class loading, ensuring that the custom classloader also conforms to the parent delegate pattern. Note that there is no specific code logic in the ClassLoader class that implements the findClass() method. Instead, it throws a ClassNotFoundException, It should also be noted that the findClass method is usually used with the defineClass method (more on that later)
defineClass(byte[] b, int off, int len)
The defineClass() method is used to parse the byte stream into a Class object that the JVM can recognize (the logic for this method is already implemented in the ClassLoader). This method allows you to instantiate Class objects not only from a Class file, but also in other ways. The defineClass() method is usually used with the findClass() method. In general, when customizing Class loaders, The findClass() method of the ClassLoader is overridden directly and a loading rule is written, the bytecode of the Class to be loaded is converted into a stream, and the Class object of the Class is generated by calling defineClass()
resolveClass(Class c)
Using this method, the Class object of the Class can be created and resolved at the same time. Earlier we said that the linking phase is mainly about verifying the bytecode, allocating memory and setting initial values for class variables and converting symbolic references in the bytecode file to direct references.
Four, hot deployment
For Java applications, hot deployment means updating Java class files at run time.
1. What is the principle of hot deployment
To understand how hot deployment works, you must understand the loading process of Java classes. A Java class file to an object in a virtual machine goes through the following process.
First, the Java compiler compiles Java files into class bytecode, and the class loader reads the class bytecode, and then converts the class into an instance, newInstance to the instance to generate objects.
The ClassLoader function, which translates class bytecode to an instance of a class.
In A Java application, all instances are loaded by the class loader.
In general, classes are loaded by the system’s own class loader, and Java classes with the same fully qualified name (such as com.csiar.soc.HelloWorld) can only be loaded once and cannot be unloaded.
This is where the problem arises. What if we want to uninstall Java classes and replace them with newer versions?
Since in the classloader, Java classes can only be loaded once and cannot be unloaded. Can we just change the classloader? The answer is yes, we can customize the ClassLoader and rewrite the findClass method of the ClassLoader. There are three steps to hot deployment:
- Destroy the custom ClassLoader
- Update the class file
- Create a new ClassLoader to load the updated class file.
2. Hot deployment and hot loading
2.1 Connection and difference between Java hot deployment and Java hot loading
Java hot deployment and hot loading
- Compile/deploy the project without restarting the server
- Java-based class loader implementation
Differences between Java hot deployment and hot loading
- Deployment way
- Hot deployment redeploys the project while the server is running
- Hot loading reloads the class at run time
- Realize the principle of
- Hot deployment directly reloads the entire application
- Hot loading reloads the class at run time
- Usage scenarios
- Hot deployment is more often used in production environments
- Hot loading is more commonly used in real development environments
3. Relevant codes
User has no modified class
Public class User {public void add() {system.out.println ("addV1, not modified... ); }}Copy the code
The User update the class
Public class User {public void add() {system.out.println (); ); }}Copy the code
Custom class loaders
public class MyClassLoader extends ClassLoader { @Override protected Class<? > findClass(String name) throws ClassNotFoundException {try {// fileName String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class"; InputStream is = this.getClass().getResourceasStream (fileName); Byte [] b = new byte[is.available()]; is.read(b); Return defineClass(name, b, 0, b.length); return defineClass(name, b, 0, b.length); } catch (Exception e) { throw new ClassNotFoundException(); }}}Copy the code
Update the code
public class Hotswap { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, InterruptedException { loadUser(); System.gc(); Thread.sleep(1000); File file1 = new File("F:\\test\ user.class "); File file2 = new File("F:\ test\ test\ target\ classes\ com\ itmayiedu\ user.class "); boolean isDelete = file2.delete(); // Delete the old class file if (! IsDelete) {system.out.println (" Hot deployment failed."); return; } file1.renameTo(file2); System.out.println("update success!" ); loadUser(); } public static void loadUser() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { MyClassLoader myLoader = new MyClassLoader(); Class<? > class1 = myLoader.findClass("com.test.User"); Object obj1 = class1.newInstance(); Method method = class1.getMethod("add"); method.invoke(obj1); System.out.println(obj1.getClass()); System.out.println(obj1.getClass().getClassLoader()); }}Copy the code
Personal blog Snail