Class loading mechanism of--java of JVM series Learning

Source: Internet
Author: User

Reprinted: 1190000004597758

This paper mainly discusses the loading mechanism of Java class, including the class loader, loading process and initialization time.

First, class loader 1, ClassLoader abstract class

The task of the ClassLoader is to read the binary bytes of this class to the inside of the JVM according to the fully qualified name of a class, and then convert to a Java.lang.Class object instance corresponding to the target class.

If you need to support dynamic loading of a class or need to decrypt a compiled bytecode file, you need to deal with the ClassLoader.

    • Bootstrapclassloader, written by C + +, is nested within the JVM, responsible for loading all types in the "Java_home/lib" directory, or all types in the path specified by "-xbootclasspath".

    • Both Extclassloader and appclassloader inherit into the ClassLoader abstract class, written by Java.

    • Extclassloader is responsible for loading all types under the "Java_home/lib/ext" directory.

    • Appclassloader is responsible for loading all types in the Classpath directory.

The DefineClass method converts a byte array of bytecode into an instance of a class object, and if you want to be linked when the class is loaded inside the JVM, you can call the Resolveclass method.

2. Parental assignment model

Parents delegation model, the parent-delegate models, contract the loading mechanism of the classloader.

When a class loader receives a task loaded by a class, it does not immediately expand the load, but instead delegates the load task to its superclass loader, and each layer of classes takes the same approach until it is delegated to the topmost startup class loader. If the superclass loader fails to load the class delegated to it, the load task of the class is returned to the next class loader to perform the load.

The working process of the parent delegation model is that if a class loader receives a request for a class load, it first does not attempt to load the class itself, but instead delegates the request to the parent ClassLoader to complete, so that all the load requests should eventually be routed to the top-level startup ClassLoader. The child loader tries to load itself only when the parent loader has feedback that it cannot complete the load request (it does not find the desired class in its search scope).

The Advantage of this approach is that it is possible to effectively ensure the global uniqueness of a class, and when there are multiple fully qualified classes in the program, the ClassLoader always loads only one of the classes when it executes the load.

The obvious benefit of using the parental delegation model to organize relationships between ClassLoader is that the Java class has a hierarchical relationship with precedence as its ClassLoader . For example, the class Java.lang.Object, which is stored in the Rt.jar, regardless of which classloader to load the class, is ultimately delegated to the startup ClassLoader at the top of the model to load, so the Object class is the same class in the various class loader environments of the program. Conversely, if the parent delegation model is not used by each classloader to load itself, If the user has written a class called Java.lang.Object, and placed in the program's Class-path, there will be a number of different object classes in the system, the most basic behavior of the Java type System can not be guaranteed, the application will become chaos. If you write a Java class that has the same name as a class that already exists in the Rt.jar class library, you will find that it compiles correctly, but it can never be loaded and run .

The parental delegation model is important to ensure the stable operation of the Java program, but its implementation is very simple, the implementation of the parent-delegated code is concentrated in the Java.lang.ClassLoader LoadClass () method, the logic is clear and understandable: first check whether it has been loaded, The LoadClass () method of the parent loader is called if it is not loaded, and the boot class loader is used as the parent loader by default if the parent loader is empty. If the parent class fails to load, the ClassNotFoundException exception is thrown, and then the Findclass () method is called to load .

Parental delegation mechanism is only the Java Virtual Machine specification recommended loading mechanism, actually in Tomcat, the loading mechanism used by the ClassLoader is different from the traditional parental delegation model, when the default ClassLoader receives a class loading task, it will first be loaded by itself, when it fails to load , the load task for the class is delegated to its superclass loader to execute .

3. Custom class Loader

If the class loader is not explicitly specified in the program, the default is Appclassloader to load, it is responsible for loading all types in the Classpath directory, and if the loaded type is not in the Classpath directory, Throws a Java.lang.ClassNotFoundException exception.

It is generally inherited ClassLoader, overriding the Findclass method if you want to conform to the parental delegation specification, overriding the LoadClass method if you want to break it.

The first "destruction" of the parent delegation model occurs before the parent delegation model occurs-before JDK 1.2 is released. Since the parent delegation model was not introduced until after JDK 1.2, The class loader and abstract class Java.lang.ClassLoader have existed in the JDK1.0 era, and in the face of existing user-defined class loader implementation code, Java designers have to make some compromises when introducing parental delegation models.

For forward compatibility, java.lang.ClassLoader after JDK 1.2 added a new protected method Findclass (), before which The only purpose for the user to inherit Java.lang.ClassLoader is to override the LoadClass () method, because the virtual machine calls the loader's private method loadclassinternal () when the class is loaded. And the only logic of this method is to call your own Load-class ().

In the previous section we have seen the code of the LoadClass () method, the specific logic of the parent delegation is implemented in this method, after JDK1.2 has not advocated the user to overwrite the LoadClass () method, but should write their own class loading logic into the Findclass () method , in the logic of the LoadClass () method, if the parent class fails to load, it calls its own Findclass () method to complete the load, which guarantees that the newly written ClassLoader is compliant with the parental delegation rules .

Second, class loading process

A complete class loading process must undergo the three steps of loading, connecting, initializing:

1. Loading

Simply put, the class loading phase is the class loader that is responsible for reading this class of binary bytes to the inside of the JVM based on the fully qualified name of a class, and storing the method area in the run-time memory area. It is then converted to a Java.lang.Class object instance corresponding to the target type (the Java Virtual Machine specification is not explicitly required to be stored in the heap, but the hotspot chooses to store the class object in the method area), and the class object will be accessed later as a variety of data for that class in the method area. Entrance.

2. Connection

The connection phase is to merge the class data information that is loaded into the binary byte stream in the JVM into the runtime state of the JVM by validating, preparing, and parsing three phases.

(1) Verification phase
Verify that the class data information conforms to the JVM specification and is a valid bytecode file, which covers the format validation, semantic analysis, operation verification, etc. of the class data information

Format validation: Verify compliance with class file specifications, such as starting with 0xCAFEBABE, size version number, etc.

Semantic validation:
A, check whether a type that is marked as final contains a derived class
b, check whether the final method in a class is overridden by a derived class
c, ensure that there are no incompatible method declarations between the superclass and the derived class (for example, the method signature is the same, but the return value of the method is different)

Operation Verification:
The data in the operand stack must be properly manipulated to perform validation on the various symbol references in the constant pool (usually performed during the parsing phase, to check whether the fully qualified name described in the symbol reference is anchored to the specified type, and whether access modifiers for class member information are allowed access, etc.).

(2) Preparation stage
Allocates memory space for all static variables in the class and sets an initial value for it (the instance variable will no longer be in scope because the object has not yet been produced)

(3) Parsing phase
Converts all symbol references in a constant pool to direct references (Gets the class or field, a pointer to the method in memory, or an offset to call the method directly). This stage can be executed after initialization.

3. Initialization

The code that identifies all the static keywords in a class is executed uniformly once, and if a static variable is executed, the initial value that was previously set in the Prep phase is overwritten with the user-specified value, and in the initialization phase, The JVM executes all the operations defined in the static code block.

All class-Variable initialization statements and static code blocks are placed in the collector by the front-end compiler at compile time and stored in a special method, which is the <clinit> method, the class/interface initialization method. The function of this method is to initialize a variable in a class, overwriting the initial value previously set in the preparation phase with a user-specified value. The <clinit> method cannot be called by any byte code such as Invoke, because the method can only be called by the JVM during class loading.

If the superclass is not initialized yet, the superclass initialization is preferred, but the <clinit> method of calling the superclass is not displayed inside the <clinit> method, and the JVM is responsible for ensuring that the <clinit> method of a class executes before its superclass < The Clinit> method has been executed.

The JVM must ensure that a class is initialized and, if it is multithreaded, it needs to be initialized at the same time, only one of the threads can be allowed to initialize it, and the remaining threads must wait until the active thread finishes initializing the class to notify other threads that are waiting.

Only those types that need to execute Java code to perform assignment operations on class variables will have a generated <clinit> method in the bytecode after compilation. If a class does not declare any class variables, and there is no static code block, the class will not contain the <clinit> method after compiling to bytecode, and if a class declares a class variable, However, the initialization of the class variable is not explicitly used, and the static code block to perform the initialization, there is no <clinit> method in the compiled bytecode, and only the final static variable will not have the method.

6 kinds of timing for class initialization

(1) When creating a new object instance for a type (e.g. new, reflection, serialization)

(2) When invoking a static method of a type (that is, executing the invokestatic instruction in the bytecode)

(3) Calling a static field of a type or interface, or performing an assignment on those static fields (that is, executing a getstatic or putstatic instruction in the bytecode), except for the final decorated static field, which is initialized to a compile-time-constant expression

(4) When invoking a reflection method in Javaapi (such as calling a method in Java.lang.Class, or java.lang.reflect a method of another class in a package)

(5) When initializing a derived class of a class (the Java Virtual Machine specification explicitly requires initialization of a class, its superclass must be initialized in advance, the interface exception)

(6) When the JVM starts the startup class that contains the main method.

The array itself is not created by the ClassLoader, but is created directly by the JVM as needed at run time, but the element type of the array still relies on the ClassLoader to be created.

Class loading mechanism of--java of JVM series Learning

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.