总结一下类加载过程,并写一些demo
类加载的过程包括: 加载-连接(验证,准备,解析)-初始化
- 加载:Loader 通过二进制码生成一个 Class 对象的过程。会把字节码转储为方法区运行时的数据结构
- 验证:是为了确保Class文件的数据符合虚拟机规范,其中包括:文件格式、元数据验证(保证符合java语义),字节码验证(保证符合),符号引用验证
- 准备:为类变量分配内存空间并且设置初始值的过程(static int value)。
- 解析:虚拟机把常量池内的符号引用替换成直接引用的过程。
- 初始化:执行类构造器的过程,这一部分会更加接近程序员开发
Demo
- 初始化和简单的解析过程
public class InitSort {
static class Parent {
public static int A = 1;
static {
System.out.println("parant: A:" + A);
A = 2;
}
}
static class Sub extends Parent {
public static final int C = 10; // 解析阶段完成符号变量->直接引用的设置
public static int B = A; // 初始化阶段会先于 static {} 模块执行
static {
System.out.println("Sub B:" + B);
B = 3;
}
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// 使用 static final int 类不会触发初始化,这是解析阶段就已经完成的。
System.out.println("不会触发初始化的:Sub.C:" + Sub.C);
// loadClass 也不会触发初始化,解析
Class<?> clazz = InitSort.class.getClassLoader().loadClass("learn.macro.mall.jvm.classloader.InitSort$Sub");
// forName 会触发初始化,这是 jdbc 触发 mysql 连接的一种方式,内部使用static代码块进行处理
InitSort.class.forName("learn.macro.mall.jvm.classloader.InitSort$Sub");
}
}
输出:
不会触发初始化的:Sub.C:10
parant: A:1
Sub B:2
观察一个字节码的常量池
java git:(master) ✗ javap -verbose learn/macro/mall/jvm/classloader/ByteCodeSample.class
Classfile /Users/qpm/work/github/mall/mall-demo/src/main/java/learn/macro/mall/jvm/classloader/ByteCodeSample.class
Last modified 2020-4-3; size 291 bytes
MD5 checksum 5f7f9cd63aa238e2d1ae6d95c5884789
Compiled from "ByteCodeSample.java"
public class learn.macro.mall.jvm.classloader.ByteCodeSample
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool: // 这里就是常量池,class文件内,常量池是一个符号引用,解析阶段会将这些符号应用改成直接引用,让JVM可以直接定位到方法、变量的内存位置。
#1 = Methodref #3.#12 // java/lang/Object."<init>":()V
#2 = Class #13 // learn/macro/mall/jvm/classloader/ByteCodeSample
#3 = Class #14 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 add
#9 = Utf8 (II)I
#10 = Utf8 SourceFile
#11 = Utf8 ByteCodeSample.java
#12 = NameAndType #4:#5 // "<init>":()V
#13 = Utf8 learn/macro/mall/jvm/classloader/ByteCodeSample
#14 = Utf8 java/lang/Object