Java improve the seventh class loader analysis
Today, we will learn about class loaders. Class loaders actually have a lot to do with the JVM. This article only briefly introduces class loaders. Later, when we learn about the JVM, we will talk about class loaders in detail. This article is divided into the following sections:
1、 Recognize class loader
1. What is a class loader?
The so-called classloader can be understood from its function. Its function is to store the classpath directory Class file, load it into memory for some processing, and the result is some bytecode Who loaded these class classes into memory? Class loader.
2. What are the default class loaders in the JVM?
Multiple class loaders can be installed in the Java virtual machine. The system defaults to three main class loaders. Each class loader is responsible for loading classes in different locations: bootstrap, extclassloader and appclassloader
Note that:
1. The class loader itself is also a Java class, because the class loader itself is also a Java class. Who loaded this special Java class [class loader]? Obviously, there should be the first class loader. This first class loader is not a Java class, it is bootstrap.
2. Bootstrap is not a Java class and does not need to be loaded by class loader. It is nested in the Java virtual machine kernel. When the Java virtual machine kernel has been started, it is already there. It is a piece of binary code written in C + + language. He can load other classes, including class loaders [such as ext and app mentioned above].
Case:
Let's write an example to get the name of the classloader of classloadertest. The code is as follows:
The results are as follows:
sun. misc. Launcher$ AppClassLoader@1c78e57 sun. misc. Launcher$AppClassLoader null null
Result analysis:
The name of the classloader for classloadertest is appclassloader. That is, this class is loaded by the appclassloader class loader. The classloader for system / ArrayList is null. This indicates that the class loader is loaded by bootstrap. As we said above, bootstrap is not a Java class and does not need to be loaded by a class loader. So his classloader is null================================== We said that Java provides us with three kinds of loaders: bootstrap, extclassloader and appclassloader. These three kinds of loaders have a parent-child relationship and form a tree structure. Bootstrap is the root node. Extclassloader is hung under bootstrap and appclassloader is hung under extclassloader
The code is demonstrated as follows:
The output result is:
sun. misc. Launcher$AppClassLoader-->sun. misc. Launcher$ExtClassLoader-->null
It can be seen from this program that classloadertest is loaded by appclassloader, the parent node of appclassloader is extclassloader, and the parent node of extclassloader is bootstrap.
Each class loader has its own jurisdiction. The bootstrap root node is only responsible for loading the classes in rt.jar. The system just belongs to the rt.jar package, and extclassloader is responsible for loading JRE / lib / ext / * Jar files in this directory folder. Appclassloader is responsible for loading all jar files and directories in the classpath directory. The last level is our custom loader, whose parent class is appclassloader.
2、 Parental delegation mechanism of class loader
In addition to the system's own class loader, we can also customize the class loader. Then hang your class loader on the tree. As a child of a class loader. All custom class loaders inherit classloader. A method classloader () in the implementation is as follows:
Through the above knowledge, we know that Java provides three class loaders, and we can also customize the class loader. We can also see the previous relationship through the class loading diagram above. Then for a class Who loads class?
When the Java virtual machine wants to load the first class, which class loader is sent to load it?
(1). First, the class loader of the current thread loads the first class in the thread (class loader of the current thread: there is a get / setContextClassLoader (classloader CL) in the thread class); Method to get / specify the class loader in this thread)
(2). If class B is referenced in class A, the Java virtual machine uses the class loader that loads class A to load class B
(3). You can also directly call classloader Loadclass (string classname) method to specify a class loader to load a class
When each class loader loads a class, it first delegates it to its parent class loader. When all ancestor class loaders are not loaded into the class and return to the initiator class loader, they will throw classnotfoundexception. Instead of looking for the son of the initiator class loader, there is no getchild() method. For example, as shown in the above figure: myclassloader - > appclassloader - > ext - > classloader - > bootstrap The self-defined myclassloader1 will first be delegated to appclassloader, appclassloader to extclassloader, and extclassloader to bootstrap. At this time, bootstrap will load. If the loading is successful, it will end. If the loading fails, it will be handed over to extclassloader to load. If the extclassloader loads successfully, it will end. If the loading fails, it will be handed over to appclassloader to load. If the loading fails, it will end. If the loading fails, it will be handed over to the custom myclassloader1 class loader to load. If the loading fails, it will report classnotfoundexception and end.
What are the benefits? It can be managed centrally without duplication of multiple byte codes. There are two classes to be loaded in the system. If the underlying class loader is loaded, two bytecodes may appear. And let Grandpa load it. Grandpa loads it. When there is another request, Grandpa said: Hey, I loaded it. I'll take it out directly for you. There will be no duplication of multiple bytecodes.
Now there is an interview question: can you write a set of Java lang.System.?
Analysis: you write in vain, because the class loader loads, go directly to grandpa to find it. If you succeed, you won't come back to deal with your one. Answer: usually not, because the delegation mechanism is delegated to Grandpa. Grandpa will not load the system class you wrote after the rt.jar package is loaded into this class. However, I also have a way to load. I write my own class loader, don't let him use the delegation mechanism, and don't delegate to the superior
Because the jar classes provided by systems such as system class, list and map are all in rt.jar, they are loaded by the bootstrap class loader. Because bootstrap is an ancestor class and is not written in Java, the printed class is null
For the loading process of classloadertest class, the print results are also very clear.
3、 Custom class loader
Let's take a look at how to define our own class loader, myclassloader:
The custom class loader must inherit the abstract class classloader and override the findclass method. In fact, it also has a loadclass method and a defineclass method. The functions of these two methods are:
Source code of loadclass method:
Let's take another look at the source code of the loadclass (name, false) method:
You can also see the principle of class loading mechanism in loadclass code. Here is the method findbootstrapclassornull. Take a look at the source code:
It is to check if name is correct, then call the findBootstrapClass method, but the findBootstrapClass method is a native local method. We can not see the source code, but we can guess that the class loader is loaded by the Bootstrap class loader. We can not rewrite this method, because if we rewrite this method, we will destroy the delegation mechanism. We have to write a delegation mechanism ourselves.
The method of defineclass is very simple. It is to program a class object from the byte array of the class file. This method can not be rewritten. The internal implementation is implemented in C / C + + code. The findclass method finds the class file according to the name and is used in the loadclass method. Therefore, we can only rewrite this method. As long as we find the class file in this method, Then use the defineclass method to return a class object.
The execution flow of these three methods is: each class loader: loadclass - > findclass - > defineclass
After understanding the previous knowledge, it will be realized now
First, let's take a look at a class that needs to be loaded: classloaderattachment java:
This class can output a paragraph: compile it into classloaderattachment class
Let's take a look at the custom myclassloader java:
This class defines an encryption and decryption algorithm. It is very simple to XOR bytes and oxff, and this algorithm can be used for encryption and decryption!
Of course, we also need to do one operation first, that is, to add classloaderattachment The class encrypted file is saved, which is executed in the main method. Here, I create a new one in the project
At the same time, the value is assigned in the form of parameters, so the input parameters should be configured when running myclassloader: right click myclassloader - > run as - > Run configurations
The first parameter is classloaderattachment The source path of the class file. The second parameter is the directory stored after encryption. After running myclassloader, refresh the class_ Temp folder, classloaderattachment Class, this is the encrypted class file.
Let's take a look at the test class:
The results are as follows:
sun. misc. Launcher$ AppClassLoader@6b97fd sun. misc. Launcher$AppClassLoader null null sun. misc. Launcher$AppClassLoader-->sun. misc. Launcher$ExtClassLoader-->null ClassLoader:sun. misc. Launcher$AppClassLoader Hello ClassLoader!
At this time, we will find that the class loader of the called app then outputs the results. This is normal because the parental delegation mechanism will be adopted at this time.
At this time, we will overwrite the classloaderattachemet class file generated by ourselves with the class file generated during compilation to see how the result is. If it is normal, an error should be reported, because this class file can be found in the corresponding classpath through the parental delegation mechanism at this time, so the app class loader will process it, However, because our class is encrypted, an error will be reported. The operation results are as follows:
So how do we get it to our custom class loader? Just put it in the directory generated during compilation Delete the class file. If the app cannot be loaded, it will call findclass, and then go to the class loader defined by us. The operation results are as follows:
reference material:
Teacher Zhang Xiaoxiang Java enhancement video
The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support programming tips.