In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "what is the loading mechanism of Java class". The content of the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "what is the loading mechanism of Java class".
1. What is class loading
Class loading refers to reading the binary data from the class's .class file into memory, placing it in the method area of the runtime data area, and then creating a java.lang.Class object in the heap area to encapsulate the data structure of the class in the method area. The final product of class loading is the Class object located in the heap area. The Class object encapsulates the data structure of the class in the method area and provides the Java programmer with an interface to access the data structure in the method area.
The classloader does not need to wait for a class to be actively used before loading it. The JVM specification allows the classloader to preload a class when it expects it to be used. If a .class file is missing or there is an error during preloading, the classloader must report an error (LinkageError error) when the program actively uses the class. If the class has not been actively used by the program Then the classloader will not report an error
2. The life cycle of the class
The process of class loading includes five stages: loading, verification, preparation, parsing and initialization. Of these five phases, the order in which loading, validation, preparation, and initialization occur is determined, while the parsing phase is not necessarily, which in some cases can start after the initialization phase to support the runtime binding (also known as dynamic or late binding) of the Java language. Also note that the phases here start sequentially rather than sequentially, because these phases are usually mixed with each other, usually invoking or activating another during the execution of one phase.
Loading: finding and loading binary data for a class
The * stages of the class loading process during loading. During the loading phase, the virtual machine needs to complete the following three things:
1. Get the binary byte stream defined by a class through its fully qualified name.
2. Transform the static storage structure represented by this byte stream into the run-time data structure of the method area.
3. Generate a java.lang.Class object representing this class in the Java heap as the access entry to the data in the other's law area.
Compared to other stages of class loading, the loading phase (to be exact, the act of fetching the binary byte stream of a class) is a controllable phase, because developers can either use the system-provided class loader to complete the load, or customize their own class loader to complete the load.
After the loading phase is complete, the binary byte stream outside the virtual machine is stored in the method area in the format required by the virtual machine, and an object of the java.lang.Class class is created in the Java heap so that the data in the method area can be accessed through that object.
Connect
-verify: ensure the correctness of the loaded class
Verification is the * * step of the connection phase, which is to ensure that the information contained in the byte stream of the Class file meets the requirements of the current virtual machine and does not compromise the security of the virtual machine itself. The verification phase roughly completes four stages of inspection:
File format verification: verify that the byte stream conforms to the Class file format specification; for example, whether the byte stream starts with 0xCAFEBABE, whether the major and minor version numbers are within the processing scope of the current virtual machine, and whether the constants in the constant pool have unsupported types.
Metadata validation: semantic analysis of the information described by the bytecode (note: compare the semantic analysis of the javac compilation phase) to ensure that the information described conforms to the requirements of the Java language specification; for example: whether this class has a parent class, except java.lang.Object.
Bytecode verification: through the analysis of data flow and control flow, it is determined that the program semantics are legal and logical.
Symbol reference validation: ensure that the parsing action is performed correctly.
The validation phase is very important, but not necessary, it has no effect on the run time of the program, and if the referenced class has been validated repeatedly, consider using the-Xverifynone parameter to turn off most of the class validation measures to shorten the virtual machine class loading time.
-prepare: allocate memory for static variables of the class and initialize them to default values
The preparation phase is the stage that formally allocates memory for class variables and sets the initial values of class variables, all of which will be allocated in the method area. There are the following points to pay attention to at this stage:
1. At this time, memory allocation includes only class variables (static), but not instance variables, which will be allocated in the Java heap along with the object when the object is instantiated.
2. The initial value set here is usually the default zero value of the data type (such as 0, 0L, null, false, etc.), rather than the value explicitly assigned in the Java code.
Suppose a class variable is defined as: public static int value = 3
Then the initial value of the variable value after the preparation phase is 0, not 3, because no Java method has been executed yet, and the putstatic instruction that assigns value to 3 is stored in the class constructor () method after the program is compiled, so the action of assigning value to 3 will not be performed until the initialization phase.
There are also a few points to note here:
For basic data types, class variables (static) and global variables will be given a default zero value if they are not explicitly assigned to them, while local variables must be explicitly assigned values before use, otherwise they will not pass at compile time.
Constants modified by both static and final must be explicitly assigned to them at the time of declaration, otherwise they will not pass at compile time; and constants modified only by final can be explicitly assigned to them either at declaration time or during class initialization, in short, they must be explicitly assigned before use, and the system will not give them a default zero value.
For reference data type reference, such as array reference, object reference, etc., if it is not explicitly assigned to it and directly used, the system will give it the default value of zero, that is, null.
If no values are assigned to the elements in the array during array initialization, the elements in the array will be assigned a default zero value based on the corresponding data type.
3. If there is a ConstantValue attribute in the field property table of the class field, that is, it is modified by both final and static, then the variable value will be initialized to the value specified by the ConstValue attribute in the preparation phase.
Suppose the above class variable value is defined as: public static final int value = 3
At compile time, Javac will generate the ConstantValue attribute for value, and in the preparation phase, the virtual machine will assign value to 3 according to the settings of ConstantValue. This is the case when you recall the second example of an object passive reference in the previous blog post. We can understand that the static final constant puts its result in the constant pool of the class that calls it at compile time.
-parsing: converts symbolic references in a class to direct references
The parsing phase is the process in which the virtual machine replaces the symbolic reference in the constant pool with direct reference. parsing actions are mainly aimed at seven types of symbolic references: classes or interfaces, fields, class methods, interface methods, method types, method handles and call point qualifiers. A symbolic reference is a set of symbols that describe the target, which can be any literal quantity.
A direct reference is a pointer directly to the target, a relative offset, or a handle that indirectly locates to the target.
Initialize
Initialization, giving the correct initial value to the static variables of the class, JVM is responsible for initializing the class, mainly initializing the class variables. There are two ways to initialize class variables in Java:
① declares that the class variable is the specified initial value
② uses static code blocks to specify initial values for class variables
JVM initialization step
1. If the class has not been loaded and connected, the program loads and connects the class first
2. If the direct parent class of the class has not been initialized, initialize its direct parent class first
3. If there are initialization statements in the class, the system executes these initialization statements in turn
Class initialization time: only when the active use of the class will lead to the initialization of the class, the active use of the class includes the following six types:
-create an instance of the class, that is, the way new
-access the static variable of a class or interface, or assign a value to it
-call the static method of the class
-reflection (e.g. Class.forName ("com.shengsiyuan.Test"))
-initializes a subclass of a class, its parent class is also initialized
-the Java Test marked as the boot class when the Java virtual machine starts, and directly uses the java.exe command to run a main class
End the life cycle
The Java virtual machine will end its life cycle in the following situations
-the System.exit () method was executed
-end of normal execution of the program
-the program terminates abnormally when it encounters an exception or error during execution
-Java virtual machine process termination due to operating system error
3. Class loader
Looking for a class loader, let's start with a small example
123456789package com.neo.classloader;public class ClassLoaderTest {public static void main (String [] args) {ClassLoader loader = Thread.currentThread (). GetContextClassLoader (); System.out.println (loader); System.out.println (loader.getParent ()); System.out.println (loader.getParent (). GetParent ());}}
After running, output the result:
123sun.misc.Launcher$AppClassLoader@64fef26asun.misc.Launcher$ExtClassLoader@1ddd40f3null
As you can see from the above results, the parent Loader of ExtClassLoader is not obtained, because the Bootstrap Loader (bootstrap classloader) is implemented in C, and there is no definite way to return the parent Loader, so null is returned.
The hierarchical relationship of these kinds of loaders is shown in the following figure:
Note: here the parent class loader is not implemented through inheritance relationships, but by composition.
From the perspective of the Java virtual machine, there are only two different kinds of classloaders: the startup classloader: it is implemented using C++ (here only Hotspot, the default virtual machine after JDK1.5, there are many other virtual machines implemented in Java), which is part of the virtual machine itself. All other class loaders: these class loaders are implemented in the Java language, independent of the virtual machine, and all inherit from the abstract class java.lang.ClassLoader, which needs to be loaded into memory by the startup class loader before loading other classes.
From the perspective of Java developers, classloaders can be roughly divided into the following three categories:
Startup class loader: Bootstrap ClassLoader, which is responsible for loading class libraries stored in JDK\ jre\ lib (JDK represents the installation directory of JDK, the same below), or in the path specified by the-Xbootclasspath parameter, and can be recognized by the virtual machine (such as rt.jar, all classes starting with java.* are loaded by Bootstrap ClassLoader). The startup class loader cannot be referenced directly by the Java program.
Extension class loader: Extension ClassLoader, which is implemented by sun.misc.Launcher$ExtClassLoader and is responsible for loading all class libraries in the DK\ jre\ lib\ ext directory or in the path specified by the java.ext.dirs system variable (such as classes at the beginning of javax.*). Developers can use the extension class loader directly.
Application class loader: Application ClassLoader, this class loader is implemented by sun.misc.Launcher$AppClassLoader, which is responsible for loading the class specified by the user classpath (ClassPath). Developers can use this class loader directly. If the application has not customized its own class loader, this is generally the default class loader in the program.
Applications are loaded by these three types of loaders, and we can add custom class loaders if necessary. Because JVM's native ClassLoader only knows how to load standard java class files from the local file system, if you write your own ClassLoader, you can do the following:
1) automatically verify the digital signature before executing the unbelievable code.
2) dynamically create custom build classes that meet the specific needs of users.
3) get the java class from a specific location, such as in the database and the network.
JVM class loading mechanism
Overall responsibility, when a class loader is responsible for loading a Class, other Class that the Class depends on and references will also be loaded by the class loader, unless it is shown to use another class loader to load
Parent class delegate, first let the parent class loader try to load the class, and try to load the class from its own classpath only if the parent class loader cannot load the class
Caching mechanism, caching mechanism will ensure that all loaded Class will be cached. When a certain Class is needed in the program, the class loader first looks for the Class from the cache. Only if the cache does not exist, the system will read the corresponding binary data of this class, convert it into Class objects, and store it in the cache. This is why after you modify Class, you must restart JVM before the changes to the program will take effect.
4. Class loading
Class is loaded in three ways:
1. When the command line starts the application, JVM initializes and loads it.
2. Dynamic loading through Class.forName () method
3. Dynamic loading through ClassLoader.loadClass () method
Example:
12345678910111213package com.neo.classloader;public class loaderTest {public static void main (String [] args) throws ClassNotFoundException {ClassLoader loader = HelloWorld.class.getClassLoader (); System.out.println (loader); / / use ClassLoader.loadClass () to load the class, no initialization block loader.loadClass ("Test2"); / / use Class.forName () to load the class, default initialization block / / Class.forName ("Test2") / / use Class.forName () to load the class and specify ClassLoader. Static block / / Class.forName ("Test2", false, loader) is not executed during initialization;}}
Demo class
12345public class Test2 {static {System.out.println ("static initialization block executed!") ;}}
If you switch the loading mode separately, you will have different output results.
The difference between Class.forName () and ClassLoader.loadClass ()
Class.forName (): loads the .class file of the class into jvm, interprets the class, and executes the static block in the class
ClassLoader.loadClass (): only one thing to do is to load the .class file into the jvm, the contents of the static will not be executed, and the static block will be executed only in the newInstance.
Note:
Class.forName (name, initialize, loader) takes a parameter function that also controls whether static blocks are loaded. And only the newInstance () method is called to create the object of the class by calling the constructor.
5. Parental assignment model.
The workflow of the parent delegation model is that if a class loader receives a request for class loading, it will not try to load the class itself at first, but delegate the request to the parent loader to complete, up in turn, so, all class loading requests should eventually be passed to the top-level startup class loader, only if the parent loader does not find the desired class in its search scope That is, the child loader will try to load the class itself if the load cannot be completed.
Parent appointment mechanism:
1. When AppClassLoader loads a class, it does not attempt to load the class itself at first, but delegates the class load request to the parent class loader ExtClassLoader to complete.
2. When ExtClassLoader loads a class, it will not try to load the class itself in the first place, but delegate the class load request to BootStrapClassLoader to complete.
3. If the BootStrapClassLoader fails to load (for example, the class is not found in $JAVA_HOME/jre/lib), ExtClassLoader will be used to attempt to load
4. If ExtClassLoader also fails to load, AppClassLoader will be used to load. If AppClassLoader also fails to load, an exception ClassNotFoundException will be reported.
ClassLoader source code analysis:
123456789101112131415161718192021222324252627public Class loadClass (String name) throws ClassNotFoundException {return loadClass (name, false);} protected synchronized Class loadClass (String name, boolean resolve) throws ClassNotFoundException {/ / first determine whether the type has been loaded Class c = findLoadedClass (name) If (c = = null) {/ / if not loaded, delegate to the parent class loader or delegate to the startup class loader try {if (parent! = null) {/ / if there is a parent class loader, delegate the parent class loader to load c = parent.loadClass (name, false) } else {/ / if there is no parent class loader, check whether the class is loaded by the startup class loader, by calling the local method native Class findBootstrapClass (String name) c = findBootstrapClass0 (name);}} catch (class e) {/ / if neither the parent class loader nor the startup class loader can complete the loading task, call its own loading function c = findClass (name);} if (resolve) {resolveClass (c) } return c;}
The significance of the parental delegation model:
-system classes prevent multiple copies of the same bytecode in memory
-to ensure the safe and stable operation of Java programs
6. Custom class loader
Usually, we use the system class loader directly. However, sometimes we also need to customize the classloader. For example, the application transmits the Java bytecode through the network, in order to ensure security, these bytecodes are encrypted, so the system class loader can not load them, so it needs to be implemented by a custom class loader. Custom class loaders generally inherit from the ClassLoader class, from the above analysis of the loadClass method, we only need to override the findClass method. Let's demonstrate the flow of a custom class loader with an example:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263package com.neo.classloader; import java.io.*; public class MyClassLoader extends ClassLoader {private String root; protected Class findClass (String name) throws ClassNotFoundException {byte [] classData = loadClassData (name); if (classData = = null) {throw new ClassNotFoundException ();} else {return defineClass (name, classData, 0, classData.length);} private byte [] loadClassData (String className) {String fileName = root + File.separatorChar + className.replace ('., File.separatorChar) + ".class"; try {InputStream ins = new FileInputStream (fileName) ByteArrayOutputStream baos = new ByteArrayOutputStream (); int bufferSize = 1024; byte [] buffer = new byte [bufferSize]; int length = 0; while ((length = ins.read (buffer))! =-1) {baos.write (buffer, 0, length);} return baos.toByteArray ();} catch (IOException e) {e.printStackTrace ();} return null;} public String getRoot () {return root;} public void setRoot (String root) {this.root = root } public static void main (String [] args) {MyClassLoader classLoader = new MyClassLoader (); classLoader.setRoot ("E:\\ temp"); Class testClass = null; try {testClass = classLoader.loadClass ("com.neo.classloader.Test2"); Object object = testClass.newInstance (); System.out.println (object.getClass (). GetClassLoader ());} catch (ClassNotFoundException e) {e.printStackTrace ();} catch (InstantiationException e) {e.printStackTrace ();} catch (IllegalAccessException e) {e.printStackTrace () }}}
The core of the custom class loader is to obtain the bytecode file. If the bytecode is encrypted, the file needs to be decrypted in this class. Since this is just a demonstration, I did not encrypt the class file, so there is no decryption process. Here are a few points to note:
1. The file name passed here needs to be the fully qualified name of the class, that is, in com.paddx.test.classloading.Test format, because the defineClass method is handled in this format.
2. * * do not override the loadClass method, because it is easy to break the parent delegate mode.
3. This kind of Test class itself can be loaded by the AppClassLoader class, so we can't put com/paddx/test/classloading/Test.class under the classpath. Otherwise, due to the existence of the parent delegation mechanism, it will directly cause the class to be loaded by AppClassLoader rather than through our custom class loader.
Thank you for reading, these are the contents of "what is the loading mechanism of Java class?" after the study of this article, I believe you have a deeper understanding of what the loading mechanism of Java class is, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
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.