The loading mechanism of virtual machine classes
An overview of the
The virtual machine loads the data describing the Class from the Class file to the memory, verifies, converts, and initializes the data, and finally forms Java types that can be directly used by the VIRTUAL machine. This is the Class loading mechanism of the virtual machine.
The timing of class loading
The JVM loads a class the first time an application makes an active reference to it; a passive reference does not trigger a class load operation. That is, instead of loading all of a program’s classes into memory at the outset, the JVM only loads them in when it has to be used, and only once. So what is active quoting and what is passive quoting?
- Active reference
- New, getstatic, putstatic, invokestatic bytecode instructions are encountered, for example:
- Instantiate objects with new;
- Read or set the static field of a class (except for those modified by final);
- Call a static method of a class.
- Make a reflection call to the class;
- Initialize a class before its parent is initialized.
- This class behaves differently from an interface. When an interface is initialized, its parent interface is not required to complete the initialization, but only when the parent interface is actually used, such as referencing constants defined in the parent interface.
- When the VM starts, initialize the main class containing the main() function.
- JDK 1.7 Dynamic language support: one
java.lang.invoke.MethodHandle
The analytical result of isREF_getStatic
,REF_putStatic
,REF_invokeStatic
.
- New, getstatic, putstatic, invokestatic bytecode instructions are encountered, for example:
- Passive reference
- Reference to a superclass static field by a subclass does not cause subclass initialization;
Array[] arr = new Array[10]
; Does not trigger Array class initialization.static final VAR
At compile time it is stored in the constant pool of the calling classClassName.VAR
The reference does not trigger ClassName initialization.
That is to say, only active references listed 5 kinds of circumstances, a class can be loaded into memory, that is, the load class is lazy – load, less than you need is not loaded in advance, after all, if will never use in the operation of the program loaded into memory, it would take a method of area of memory, waste of system resources.
Class life cycle
Class loading process
loading
In the Loading phase, a VM needs to do the following three things:
- Gets the binary byte stream that defines a class by its fully qualified name
- Transform the static storage structure represented by the binary byte stream of this class into the runtime data structure of the method area
- Generate a representation of this class in the Java heap
java.lang.Class
Object that acts as an access point to this data in the method area.
classification
- The array class
- System – provided boot class loader
- User-defined class loader
- An array of class
- Created directly by the Java VIRTUAL machine without using the class loader
- The creation action is triggered by the Newarray directive, and new actually triggers the initialization of the [L full class name object
- The rules
- Array elements are reference types
- Load: Loads its components recursively
- Visibility: Consistent with the reference type
- Array elements are non-reference types
- Load: Associated with the boot class loader
- Visibility: public
- Array elements are reference types
Explicit and implicit loading of classes
- Display loading:
- call
ClassLoader#loadClass(className)
或Class.forName(className)
. - The difference between two display loading.class files:
Class.forName(className)
Loading the class initializes the static domain,ClassLoader#loadClass(className)
Static fields are not initialized;Class.forName
The class is loaded with the ClassLoader of the current caller’s class.
- call
- Implicit loading:
- New class object;
- Static fields using classes;
- Create a subclass object;
- Static fields using subclasses;
- Other implicit loads, at JVM startup:
BootStrapLoader
Loads some classes that the JVM itself needs to run;ExtClassLoader
Loads special classes in the specified directory.AppClassLoader
The Class in the classpath path and the Class file of the main function are loaded.
validation
Purpose: To ensure that byte stream information in the.class file meets the requirements of the virtual machine.
Four validation procedures:
- File format verification: Verify that the file complies with the Class file format specification. Verify that the first four bytes of the file are not the “magic number” 0xCAFEBABE
- Magic number: The first four bytes of each Class file are called magic numbers. Their only purpose is to determine whether the file is a Class file that can be accepted by the virtual machine.
- Metadata Validation: Java Specification for ensuring bytecode description Information Notation (Semantic Analysis)
- Bytecode verification: program semantics, logic correctness (through data flow, control flow analysis)
- Symbolic reference validation: Checks the match of information outside the class itself (symbolic references in the constant pool)
This operation, while important, is not necessary and can be turned off by using -xverify: None.
To prepare
Description: Allocate memory in the method area for static variables.
- The initial value of the static variable after preparation:
- public static int value = 123;
- When set to 0, the assignment instruction putStatic of value will be placed
<clinit>()
Method,<clinit>()
The method is executed at initialization, that is, the value variable is equal to 123 only after initialization.
- When set to 0, the assignment instruction putStatic of value will be placed
- public static final int value = 123;
- After preparation, value is 123, because value cannot be modified after static final assignment. Therefore, it is impossible to perform assignment after this assignment. Therefore, value can be initialized directly during preparation.
- public static int value = 123;
parsing
Description: Replace “symbolic reference” with “direct reference” in constant pool.
Before this, references in the constant pool do not necessarily exist. After parsing, references in the constant pool can be guaranteed to exist in memory.
What are “symbolic references” and “direct references”?
- Symbolic reference: A set of symbols describing the referenced object (such as the full class name of the object). The target of the reference does not necessarily exist in memory.
- Direct reference: a pointer that points directly to the location in memory of the referenced target, that is, the referenced target must exist in memory.
Initialize the
Description: The process of executing a class constructor () method.
-
<clinit>()
methods- Contents included:
- All static assignment operations;
- A statement in a static block;
-
<clinit>()
Order of statements in the method:- Basically in the order in which statements appear in the source file;
- A static block can only access variables defined before it, and variables defined after it can be assigned, but not accessed.
- 与
<init>()
The different:- You do not need to display the call parent class
<clinit>()
Methods; - Virtual machines are guaranteed in subclasses
<clinit>()
Method before execution of the parent class<clinit>()
Method must complete execution. That is, assignments to static blocks and static fields of the parent class precede those of the child class.
- You do not need to display the call parent class
- Differences between interfaces and classes:
- Executing the subinterface
<clinit>()
Method does not need to execute the parent interface first<clinit>()
Method (unless using a public static final variable defined in the parent interface);
- Executing the subinterface
- Lock during execution:
- Only one thread can be executing at a time
<clinit>()
Method, because the virtual machine must ensure that a class is loaded only once under the same classloader.
- Only one thread can be executing at a time
- Not necessary:
- A class that does not have any static content does not need to execute the () method.
- Contents included:
Addendum to this section:<clinit>
与 <init>
methods
An overview of the
When the class file is compiled, two methods are automatically generated: the class initialization method
and the instance initialization method
.
< Clinit > : called when the JVM first loads the class file, including static variable initialization statements and the execution of static blocks
: called when the instance is created, including calling the new operator; Call the Class or Java. Lang. Reflect. The Constructor object newInstance () method; Call the clone() method of any existing object; Through the Java. IO. ObjectInputStream class getObject () method deserialization.
<clinit>
methods
Understand the class initialization phase: This phase is responsible for assigning the correct initial values to class variables and is the last step before a class or interface is used for the first time
The execution period of the < Clinit > method: the class initialization phase (this method can only be called by the JVM to initialize class variables)
The contents of the < Clinit > method: static initializers for all class variable initializers and types
Class initialization timing: the first active use of a class in Java code, including the following situations:
- When a new instance of a class is created (for the first time) –new, reflection, clone, or deserialize;
- When a static method of a class is called (for the first time);
- When (for the first time) a static field of a class or interface is used or a value is assigned to that field (except for a final field);
- When some Java reflection method is called (for the first time);
- When a subclass of a class is initialized (for the first time);
- A startup class that (for the first time) contains the main() method when the virtual machine starts
Note: Not all classes will have a method. Classes that satisfy one of the following conditions will not have a method:
-
This class does not declare any class variables nor does it have a static initialization statement;
-
This class declares class variables, but does not explicitly initialize them using class variable initializers or static initializers.
-
The class contains only class variable initializers for static final variables, and the class variable initializers are compile-time constant expressions;
<init>
methods
The execution period of the
method: the initialization phase of the object
There are four ways to instantiate a class:
- Call the new operator
- Call the Class or Java. Lang. Reflect. The Constructor object newInstance () method
- Call the clone() method of any existing object
- Through the Java. IO. ObjectInputStream class getObject () method deserialization
Class loader
The class loading action of “obtaining the binary stream describing a class by its fully qualified name” is implemented outside the Java virtual machine so that applications can decide how to obtain the required classes. The code module that implements this action is called the “class loader”.
Class loaders are only used to load classes, but their role is much more than that. Comparing two classes to be “equal” requires not only that the two classes are from the same class file, but also that they are loaded by the same classloader.
How to Tell if two classes are “equal”
- The “equality” requirement
- Same.class file
- Loaded by the same VM
- Loaded by the same class loader
- The way to judge “equality”
- The instanceof keyword
- Methods in the Class object:
- equals()
- isInstance()
- isAssignableFrom()
Classification of class loaders
From a virtual machine perspective, there are only two types of loaders:
Bootstrap ClassLoader (Bootstrap ClassLoader), implemented in C++, is part of the virtual machine ClassLoader, implemented in Java language, independent of the virtual machine, all inherited from the abstract java.lang.ClassLoader
From a developer’s point of view, class loaders can be more finely divided:
- Bootstrap: Loads virtual machine recognized libraries in the \lib directory or in the path specified by the -xbootclasspath parameter into virtual machine memory.
<JAVA_HOME>/lib
-Xbootclasspath
Parameter specifies the path
- Extension class loader: Takes care of loading
<JAVA_HOME>\lib\ext
Directory, or byjava.ext.dirs
For all libraries in the path specified by the system variable, the developer can use the extended class loader directly.<JAVA_HOME>/lib/ext
java.ext.dirs
The path specified by the system variable
- Application: Loads the libraries specified on the user’s ClassPath. This is usually the default class loader in the Application.
-classpath
parameter
The above loaders work together to load our own applications, and if necessary, we can add our own loaders. The relationship between these loaders is generally shown as follows:
Parental delegation model
The Parent Delegation Model of class loaders: Requires that all class loaders have their own Parent class loaders except the top launching class loaders. (note! The parent-child relationship between classloaders is not typically achieved by Inheritance, but by Composition using the parent’s code. This model is widely used in almost all Java programs, but it is not a mandatory constraint, just one of the loader implementations Java designers recommend to developers.
- The working process of the
- Instead of trying to load the class itself, the current class loader delegates the request to the parent class loader. Therefore, all class loading requests are first passed to the launcher class loader.
- Only if the parent class loader fails to load, will the current class loader attempt to load its own region
- implementation
- Check whether the class has been loaded
- Delegate class loading requests to the parent class
- If the parent class loader is null, the startup class loader is used by default
- parent.loadClass(name, false)
- When the parent class loader fails to load
- Catch ClassNotFoundException but do nothing
- Call your own findClass() to load it
- Instead of overwriting the parent delegate mechanism in loadClass(), we simply implement the extends ClassLoader to implement our own ClassLoader and override the findClass() method instead of the loadClass() method
- advantages
- A self-written class with the same name as the library does not overwrite the library’s classes
- Java classes, along with their classloaders, have a hierarchy of priorities that ensure the stable running of Java programs.