Home>Article>Java> Jvm class loading mechanism for java learning

Jvm class loading mechanism for java learning

青灯夜游
青灯夜游 forward
2018-10-16 16:35:25 1971browse

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.

1. Overview

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.

2. Class loading timing

The class starts from being loaded into the memory by the virtual machine until it is unloaded from the memory. The entirelife cycleincludes:Loading - - Verification - Preparation - Parsing - Initialization - Use - UninstallThese 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.

What situations can trigger the initialization phase of a class? (Premise: Loading, verification, and preparation have naturally been executed)

  1. 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)

  2. When using reflection

  3. When initializing a class, if its parent class has not been initialized yet, you need to trigger the initialization of the parent class first

  4. 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

  5. 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

3. Class loading process

- Loading

Loading is a stage of class loading. During the loading stage, the virtual machine needs to complete the following three things

  1. Get the binary byte stream that defines this class through the fully qualified name of the class

  2. Convert the static storage structure represented by this byte stream into the runtime data structure of the method area

  3. 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

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.

-Preparation

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.

- Parsing

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.

-Initialization

The initialization phase is the process of executing the class constructor () method. In the preparation phase, the variables have been assigned an initial value required by the system, and in the initialization phase, class variables and other resources are initialized according to the parameter values set by the programmer.

Class constructor () method: It is generated by the compiler automatically collecting the assignment actions of all class variables in the class and merging the statements in the static code block.

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; }

() method is not necessary for classes or interfaces. If there is no static code block in a class, and there is no assignment operation to variables, the compiler does not need to do this. Class generation method

Static blocks cannot be used in interfaces, but variable assignment operations can still be performed, so interfaces and classes will generate methods. The difference is that interface initialization does not require initialization of the parent class first. The initialization of the parent interface will only be triggered when the variables in the parent interface are used. In addition, the implementation class of the interface will not trigger the instantiation of the interface.

The virtual machine ensures that the () method of a class is correctly locked and synchronized in multiple threads. If multiple threads initialize a class, only one thread will execute the class. () method, other threads are in a waiting state. Only the active thread can complete execution. If there is a long-running operation in the () method of a class, it may cause multiple threads to be blocked. In actual applications, this blocking is often very hidden.

4. Class loader

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.

From the perspective of Java developers, class loaders are roughly divided into the following three types

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 \lib\ext directory, or All class libraries in the system path specified by the java.ext.dirs system variable. Developers can use the extension class loader directly.

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种类加载器相互配合进行加载的。如果有必要,还可以加入自定义的类加载器。

这些类加载器之间的关系如下图:

5.双亲委派模型:

双亲委派模型的工作过程是:如果一个类加载器收到了一个类加载请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一层的加载器都是如此,因此所有的加载请求最终都应该到达顶层的启动类加载器。只有当父加载无法完成这个加载请求时,子加载器才会尝试自己去加载。

双亲委派机制:

1、当ApplicationClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。

2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。

3、如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;

4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。

ClassLoader源码分析:

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!

Statement:
This article is reproduced at:cnblogs.com. If there is any infringement, please contact admin@php.cn delete