-
类加载过程
- 加载
- 将class文件字节码内容加载到内存中去,在方法区保存二进制代码,在堆中生成类Class对象。可用于反射。
- 链接
- 验证
- 校验数据规范性安全性
- 准备
- 为静态变量分配内存并设置默认值
- 解析
- 将常量池里的符号引用替换为直接引用
- 常量包含:类名(确定后就不会改变),方法名,变量名,类型名
- 每个类加载到方法区后都会有一个常量池
- 将常量池里的符号引用替换为直接引用
- 验证
- 初始化
- 执行类构造器<clinit>(),类构造器方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的,是不能人为初始化的。
- 如果有父类,先执行父类的初始化
- 虚拟机确保一个类的<clinit>()方法在多线程环境中加锁和同步,确保线程安全
- 方位java类中的静态域时,只有声明这个域的类才会被初始化。
- 使用
- 卸载
- 加载
-
类的主动引用与被动引用区别
- 类的主动给引用(一定会发生初始化)
- new一个类对象
- main方法所在类一定会初始化
- 对类进行反射调用也会初始化
- 调用类的静态成员(除了final)和静态方法
- 类的被动引用(不会发生类的初始化)
- 调用常量不会类的触发类的初始化(常量在编译阶段jiuz就在类的常量池中),如final修饰的常量
- 通过数组定义类引用,不会触发类初始化 如A[] a = new A[10];不会初始化类A;
- 访问一个静态域时,只有真正声明这个域的类才会被始化
- 子类引用调用父类静态变量时,不会触发子类的初始化
- 类的主动给引用(一定会发生初始化)