This article will introduce to you the loading mechanism of Jvm class in java learning. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
The virtual machine loads the Class file (binary byte stream) into the memory, and verifies, converts, parses, and initializes the data, ultimately forming a file that can be used directly by the virtual machine. Java type, this series of processes is the loading mechanism of the class.
The class starts from being loaded into the memory by the virtual machine until it is unloaded from the memory. The entire life cycle includes: Loading - - Verification - Preparation - Parsing - Initialization - Use - Uninstall These 7 stages. The three parts of verification, preparation, and parsing are collectively called connections.
The life cycle diagram is as follows:
The order of the five phases of loading, verification, preparation, initialization, and unloading is determined, and the loading process of the class must Starting in this order, the parsing phase is not necessarily: it can start after initialization in some cases, this is also to support the dynamic binding of the Java language.
When encountering the four instructions new, getstatic, putstatic, and invokestatic, if the class has not been initialized, its initialization will be triggered. (The most common scenarios that trigger these four instructions at work: new instantiation of objects, reading or setting static fields of the class [except for final modifications or static fields that have been put into the constant pool], calling static methods of the class)
When using reflection
When initializing a class, if its parent class has not been initialized yet, you need to trigger the initialization of the parent class first
When the virtual machine starts, you need to specify a main class to be executed (the class containing the main method). The virtual machine will initialize this class first
Use When jdk1.7 dynamic language is supported, if the final parsing result of a java.lang.invoke.MethodHandle instance is the method handle of REF_getStatic, REF_putStatic, REF_invokeStatic. If the class corresponding to this handle has not been initialized, you need to trigger its initialization first
Note: All methods of referencing the class will not trigger initialization (passive reference). For example: creating an array, referencing final Modified variables and static variables of subclasses that reference parent classes will not trigger subclass initialization but will trigger parent class initialization
Loading is a stage of class loading. During the loading stage, the virtual machine needs to complete the following three things
Get the binary byte stream that defines this class through the fully qualified name of the class
Convert the static storage structure represented by this byte stream into the runtime data structure of the method area
Generate a representation of this type in memory The java.lang.Object object serves as the access point for various data of this class in the method area.
Compared with other stages of class loading, the loading stage (to be precise, in the loading stage The action of obtaining the binary byte stream of a class) is the one most controllable by the developer. Because the loading phase can be completed using the boot class loader provided by the system, or it can be completed by the developer's custom class loader (that is, overriding the loadClass() method of the class loader).
After the loading is completed, the external binary byte stream is converted into the format required by the virtual machine and stored in the method area, and then an object of the java.lang.Class class is instantiated in the memory. This object will serve as the external interface for the program to access these types of data in the method area.
Part of the loading phase and the connection phase are interleaved, and verification and other operations cannot be performed until the loading is completed. These actions sandwiched in the loading still belong to the connection phase, and the start times of these two phases still maintain a fixed sequence.
Verification is the first step in connection, in order to ensure that the information contained in the loaded binary byte stream complies with the virtual machine specifications.
The verification phase is roughly divided into the following 4 verification actions:
File format verification: Verify whether the byte stream complies with the Class file format specification. For example: whether it starts with the magic number 0xCAFEBABE, whether the major and minor version numbers are within the processing range of the current virtual machine, whether the constants in the constant pool have unsupported types...
Metadata verification: Perform semantic analysis on the information described by the bytecode. For example: Does this class have a parent class and whether it inherits the parent class correctly.
Bytecode verification: Through the analysis of data flow and control flow, determine that the program semantics is legal and logical (to put it bluntly, it means analyzing the method body of the class to ensure that the method is It will not harm the virtual machine when running).
Symbol reference verification: Ensure that the parsing action can be executed normally.
The verification phase is very important, but not necessarily a necessary phase (because it has no impact on the program running time). If all code being run has been repeatedly used and verified, verification can be turned off during the implementation phase using the -Xverify:none parameter.
Formally allocate memory for class variables and set the initial value of the class variable. The memory used by these variables will be allocated in the method area.
Note:
At this time, only static variables are allocated, not instance variables. Instance variables will be allocated together with the object instance In the Java heap
#The initial value is usually the zero value of the data type. If you define a static variable public static int value = 123; then the initial value of value is 0 instead of 123 during the preparation phase.
#The variable modified by final is initialized to the value specified by the attribute during the preparation phase. For example: public static final int value = 123; then the initial value of value in the preparation phase is 123.
The parsing phase is the process in which the virtual machine replaces symbol references in the constant pool with direct references. The parsing action is mainly performed on seven types of symbol references: classes or interfaces, fields, class methods, interface methods, method types, method handles and call site qualifiers.
Symbol reference: Use a set of symbols to describe the target of the reference. The symbols can be any form of literals.
Direct reference: a pointer to the target, a relative offset, or a handle that can indirectly locate the target.
The initialization phase is the process of executing the class constructor
Class constructor
The order in which the compiler collects is determined by the order in which statements appear in the source file; a static code block can only access variables defined before the static block, variables defined after it, and variables defined in the previous static block Values can be assigned to, but cannot be accessed.
非法向前引用示例 public class SuperClass { public static int va; static { value = 1; //可以编译通过 va = value; //报错 非法向前引用 System.out.println("父类初始化"); } public static int value = 123; }
Static blocks cannot be used in interfaces, but variable assignment operations can still be performed, so interfaces and classes will generate
The virtual machine ensures that the
The virtual machine design team put the action of "obtaining a binary byte stream describing this class through the fully qualified name of a class" in class loading into Java Implement it outside the virtual machine so that the application can decide how to obtain the required classes. The block of code that implements this action is called a class loader.
Bootstrap Classloader (Bootstrap Classloader): Responsible for storing files in < JAVA_HOME>\lib (Javahome is the jdk installation directory) directory, or in the path specified by the -Xbootclasspath parameter, and is recognized by the virtual machine (only recognized by the file name, such as rt.jar, the name does not match The class library will not be loaded even if it is placed under lib) The class library is loaded into the virtual machine memory. The startup class loader cannot be used directly by Java programs.
Extension Classloader: This loader is implemented by sun.misc.Launcher$ExtClassLoader, which is responsible for loading the
Application Classloader: This loader is implemented by sun.misc.Launcher$AppClassLoader, which is responsible for loading the class library specified on the user class path (ClassPath) . Developers can use this loader directly. If there is no custom class loader in the application, then this is the class loader executed by the program by default. (System Loader)
我们的应用程序都是由这3种类加载器相互配合进行加载的。如果有必要,还可以加入自定义的类加载器。
这些类加载器之间的关系如下图:
双亲委派模型的工作过程是:如果一个类加载器收到了一个类加载请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一层的加载器都是如此,因此所有的加载请求最终都应该到达顶层的启动类加载器。只有当父加载无法完成这个加载请求时,子加载器才会尝试自己去加载。
1、当ApplicationClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。
3、如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // 先检查此类是否已被加载 Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { //委派给父类加载器去加载 if (parent != null) { c = parent.loadClass(name, false); } else { //如果没有父加载器,则调用启动类加载器 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } //如果父加载器无法加载,则调用本身加载器去加载 if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
系统类防止内存中出现多份同样的字节码
保证Java程序安全稳定运行
参考
《深入理解Java虚拟机》
总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。更多相关教程请访问Java视频教程,java开发图文教程,bootstrap视频教程!
The above is the detailed content of Jvm class loading mechanism for java learning. For more information, please follow other related articles on the PHP Chinese website!