Article directory
foreword
Java's class loading phase is divided into: loading, linking, and initialization, and the linking process includes: verification, preparation, and resolution.
1. Loading
Load the bytecode of the class into the method area, and internally use the instanceKclass of C++ to describe the Java class
Important fields of instanceKclass:
- _java_mirror: Java class mirror, which stores the address of the class object, for example, for String, it stores String.class
- _super: the parent class
- _methods: the method
- _constants: the constant pool
- _class_loader: class loader
- _vtable: virtual method table
- _itable: interface method table
2. Links
The linking phase consists of 验证、准备、初始化
three parts
verify
Verify that the class conforms to the JVM specification, and perform security checks, for example: check the magic number of the Java file
Prepare
Allocate address space for static variables, set default values
- Static variable allocation and assignment are two steps, the allocation of space is completed in the preparation phase, and the assignment is completed in the initialization phase;
- If the static variable is of final type, and the variable type is a basic data type or a string object, it is assigned in the preparation phase;
- If the static variable is of final type and the variable type is a reference object, it is still assigned in the initialization phase;
analyze
resolves symbolic references in the constant pool to direct references
3. Initialization
Initialize call ()v, that is, execute the constructor of the class, code blocks, etc., and the virtual machine guarantees the thread safety of this class
timing
In a nutshell, class initialization is lazy
- The class where the main method is located will always be initialized first;
- The first time you access the static variable or static method of the class, because these variables are not final, they will be assigned during the initialization phase of the class;
- Subclass initialization will cause initialization of the parent class;
- The static variable of the parent class of the subclass method will cause the initialization of the parent class;
- Class.forName;
- new causes initialization;
does not trigger class initialization
- The static final static variables (basic types and strings) of the access class will not be initialized, because the assignment of these variables is in the preparation stage;
- class object.class does not trigger the initialization of the class;
- Creating an array of this class does not trigger initialization;
- The loadClass method of the class loader;
- When parameter 2 of Class.forName is false
4. Class loader
Take JDK8 as an example
name | Where to load classes | illustrate |
---|---|---|
Bootstrap ClassLoader | JAVA_HOME/jre/lib | no direct access |
Extension ClassLoader | JAVA_HOME/jre/lib/ext | Superior is Bootstrap ClassLoader, access is null |
Application ClassLoader | classpath | The superior is Extension ClassLoader |
custom class loader | custom parent | 为 Application ClassLoader |
The role of the class loader: to load the binary bytecode of the class
Parental Delegation
The parent delegation mode is a Java class loading mechanism, which defines a hierarchical parent-child relationship, and the parent class loader delegates requests downward until a suitable class loader is found.
- First, it will check the cache to find out whether the loader has already loaded this class, and if not, go to the parent class loader to find it;
- If it is not found in the cache, the class loader will be used from top to bottom to create the class;
- Finally return to this class;
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
// 检查缓存,是否已经加载过这个类
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
// 向上级的累加器中找
c = parent.loadClass(name, false);
} else {
// 向 Bootstrap 类加载器中找
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();
// 调用 findClass 去创建类
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;
}
}