In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-03 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "what is the principle of parental appointment". Friends who are interested might as well take a look. The method introduced in this paper is simple, fast and practical. Now let the editor take you to learn "what is the principle of parental appointment"!
I bet you often encounter some class loading problems in the development process, such as:
ClassNotFoundException
Cause: java.lang.ClassNotFoundException: Cannot find class: com.cc.A
NoClassDefFoundError
Cause: java.lang.NoClassDefFoundError: Cannot find class: com.cc.A
The above problems are all related to java class loading. If you are not clear about the principle of class loading in JVM, the above problems will be extremely depressing. Luckily, finding a solution online is only a temporary solution, and you will continue to be confused when you encounter it in other scenarios.
In this article, I will explain the parent delegation loading principle of the Java class loader, and combined with the example program to study the parent delegate loading mechanism of the class, we thoroughly understand the class loading principle, clear the class loading principle, encounter the above similar problems can be quickly solved, and avoid similar problems in the follow-up development.
What is Java class loading?
The java class loader is responsible for loading the compiled Java class into the runtime data area of the Java virtual machine (JVM) for call by the execution engine.
The location of the java class load in the JVM architecture is shown in the figure:
Original diagram of jvm architecture
Without class loading mechanism, the written java program cannot run in JVM, so it is very important to master java class loading.
JVM class load hierarchy
When executing the java program, a JVM process will be started, and JVM will do some initialization operations at startup, such as getting system parameters, etc., and then create a startup class loader that will be used to load some classes necessary for JVM runtime into memory, as well as two other class loaders that extend the class loader and the system class loader.
The relationship between startup class loaders, extension class loaders, and system class loaders is shown in the following figure:
Jvm built-in classLoader
* * Startup classloader: * * the first classloader created after the java virtual machine is started, which is implemented by C++ language, so when we view its information in java code, all we see is null.
Extension class loader: loaded by the startup class loader and sets the value of parent in the extension class loader to null (indicating that it points to the startup class loader) and inherits from URLClassLoader.
System class loader: loaded by the startup class loader and sets the value of parent during the system class loading period to the extended class loader created above. And inherits from URLClassLoader.
You can see the parent pointing in the class load in the code as follows:
Code view the parent of the class loader
Note: the parent here is not the inheritance mechanism of java, but an instance property in the class loader, which is used to delegate the object when the class is loaded. The parent attribute is defined in the ClassLoader to which it inherits, as defined below.
Public abstract class ClassLoader {. / / The parent class loader for delegation private final ClassLoader parent
Default load path for JVM class loading
Each type of class loader has its own load path by default, and the default load paths for starting class loaders, extension class loaders, and system class loaders are shown in the following figure:
The loading path of three kinds of loaders
As shown in the above figure:
1, the startup class loader (BootClassLoader), written by the C++ language, is responsible for loading some of jdk's own core class classes (in the form of jar packages) into JVM when JVM starts, and the path to find resources when loading is specified by the read-only system attribute: "sun.boot.class.path", generally: the "JAVA_HOME/jre/classes" directory (in this directory only class files can be put, jar package format files do not take effect).
You can view the startup class load path by getting the system property: "sun.boot.class.path", as shown in the figure:
Set the startup class load path in lancher
Start the classloader load path
2, extended class loader (ExtClassLoader), responsible for loading class files (jar package or direct class file form) into JVM under the directory pointed to by "java.ext.dirs". For example, usually the ext class load path is: "$JAVA_HOMEx/jre/lib/ext".
It is supported to modify the path before JVM starts. The modified path does not take effect while running, and only the loading of jar packages is supported in the extended classpath.
To view the classloading path of the extended classloader, you can view it by getting the system property: "java.ext.dirs" or by transforming it up to URLClassLoader (the extended classloader inherits from URLClassLoader) and viewing the urls property in the parent class URLClassLoader, as shown in the figure:
Extend the classloader path
3. The system class loader (AppClassLoader) is responsible for loading the class file (in the form of jar package or direct class file) under the application classpath path into JVM. When the classpath path is not set in the system, the class file under the current path is loaded by default.
To view the classloading path of the system classloader, you can view it by obtaining the system property: "java.class.path" or by transforming it up to URLClassLoader. It is said that the extended classloader inherits from URLClassLoader), and view the way the urls property is located in the parent class URLClassLoader, as shown in the figure:
System class loading path
JVM class loads parent delegation mechanism
When JVM loads the class class file to the virtual machine, by default, the system class loader is used to load the class class, and the parent delegate loading mechanism is adopted.
The so-called parent delegate, as the name implies, means that when the current classloader (taking the system classloader as an example) loads a class, it delegates to its parents (note that the parent here refers to the classloader that the parent attribute points to in the classloader).
The parent classloader also delegates to its own parents when loading, and so on, until a classloader has no parents (usually the parent is null, that is, the current parent is the extension classloader, whose parent is the startup classloader), and then starts to find and load class classes under their respective classpath.
As shown in the following figure:
Parental appointment
Loading instance instance by parent delegation
Adopt the JDK version
Java version "1.8.0261" Java (TM) SE Runtime Environment (build 1.8.0_261-b12) Java HotSpot (TM) 64-Bit Server VM (build 25.261-b12, mixed mode)
This example involves two classes: TestMain.java and A.java. Mid-term TestMain is the startup class. Call the method execution in class An in the startup class to output the class loader information of the startup class and the dependent class, respectively. The class definition is as follows:
A_java
TestMain
We copy the two java files to a directory, put them locally in the E:\ java_app directory, open the command line window under windows, switch to E:\ java_app, compile the current java file, and execute the command javac TestMain.java.
At this point, the corresponding class file is produced in the current directory (here you only need to execute the compile command on TestMain, because TestMain depends on A, so the Jdk compiler will automatically compile the dependent A first), as shown in the figure:
Compile command
Next we'll look at how the java class loading mechanism implements parent delegate loading.
Delegate to the extension class loader to load
Because the extension class loads under its classpath only supports finding jar packages, we package the A.class file into A.jar through the tool.
Then place the A.jar in the extension class load path: $JAVA_HOME/jre/lib/ext, while keeping the A.class file in the current directory. As shown in the figure:
Extended delegation
At this point, there is still an A.class file in the current directory: e:\ java_app, and an additional A.jar file containing A.class is added under the path of the extended classloader. Execute the java command to execute TestMain in the current directory, the command is: java TestMain, and the output is as follows:
Extend delegation result
From the output of the above figure, we can see that although class An is in the loading path of the system class loader, because of the delegated mechanism of class loading, A will first be delegated by the system class loader to its parents extension class loader to load, which happens to include A.class (included in A.jar) in the load path of the extension class loader, so An is finally loaded by the extension class loader.
Delegate to the startup class loader to load
In general, the loading of a normal class should not be delegated to the boot class loader, because as mentioned earlier, the startup class loader is implemented by C++, which is generated when the java virtual machine starts, and the information obtained from her in the java environment is null.
In order to explore the parent delegation mechanism of class loading, this example specially constructs a scenario in which a normal class is delegated to it to load.
Earlier, when talking about the boot classloader load path, it was pointed out that the boot classloader load path is specified by the read-only system property "sun.boot.class.path", and only the jar files fixed in that directory are supported.
There is also a "$JAVA_HOME/jre/classes" directory in jdk8 that is also the path to start classloader loading (this path may not exist by default, so you can create one manually). Only class files can be put in this directory, and jar package files do not take effect.
Therefore, this example program copies the A.class file in the current directory to the classpath of the startup classloader: "$JAVA_HOME/jre/classes", while keeping the A.class file in the current directory and the A.jar in the classpath of the extended classloader.
The storage path of the class is shown in the figure:
Delegate initiation
From the current directory: e:\ java_app, execute the command to run TestMain, the command is: java TestMain, and the output is as follows:
Delegate startup result
From the output of the above figure, we can see that although class An is in the loading path of the system class loader and in the loading path of the extended class loader, because of the delegated mechanism of class loading, A will first be delegated by the system class loader to its parents extended class loader to load.
The extension class loader will continue to carry out delegate loading (in fact, because the parent of the extension class loader: the startup class loader is null, so the delegate action at this time is actually to start the classloader to look for class An in the loading path of the class loader), and the startup class loads A finally.
Parental delegation loading direction
When a class loader loads a class, it can only recursively delegate its parents for class loading, but it is impossible to delegate the current class loader from the parents in reverse.
In Chinese chess, the walking track of the pawn after crossing the river can only be forward or translating left and right, which can be vividly compared to the direction of the entrusted loading of parents.
The pawn crossing the river means that the current class loader delegates its parents to load a class. The subsequent dependent loading of this class has nothing to do with the current class loader.
The pawn after crossing the river can only move forward, indicating that the parents can only continue to delegate the parents recursively when loading the dependent class of the class.
Translating left and right means that the parents load in the parent classloader's own load path after the recursive parent delegate fails.
To show that delegation is directional, let's continue to experiment with the TestMain.class and A.class classes above.
Our scenario in the above delegated example is: TestMain relies on A, and we load A through parent delegation. In this experiment, we delegate TestMain to parents to load.
According to the above steps, type TestMain.class into TestMain.jar and put it in the loading path of the extension class loader, while keeping the TestMain.class to the current directory, as shown in the following figure:
Delegate load order 1
Change to the current application directory and execute the java command to run the program: java TestMain. The execution result is as follows:
Delegate sequential execution result
As shown in the figure above, an error occurred. The TestMain was loaded by the extension class loader, but the dependent A could not be loaded into.
The reason is that the delegate loading mentioned above is directional:
1. When running the java command to execute the TestMain program, the system class loader is ready to load TestMain. According to the parent delegation mechanism, the system class loader first delegates to its parents to load. Finally, the parent extension class loader finds TestMain.class in the TestMain.jar in its loading path and completes the loading of TestMain.
2. If An is dependent on TestMain, it will load An according to the class loader that loads TestMain: the extended class loader, and the loading mode will be recursively delegated to the parents according to the delegate mechanism. The parents of the extended class loader will start the class loader, and there is no An in the loading path of the startup class loader. If loading fails, the extension class loader will load An in its own loading path. Also because there is no A.class in the loading path, A.class exists in the loading path of the system class loader, but the extended class loader will not go back to entrust the system class loader to load, so the loading failure exception is thrown directly, and the above error occurs.
At this point, I believe you have a deeper understanding of "what is the principle of parental appointment". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.