网站建设哪便宜,高校网站建设目的与意义,做分销网站系统下载,可以上传软件的网站目录
一、类加载生命周期
二、主动引用
2.1、创建类的实例
2.2、访问类的静态字段或静态方法
2.3、反射
2.4、初始化类的子类时#xff0c;先初始化父类
2.5、虚拟机启动时#xff0c;初始化 main 方法所在的类
2.6、动态语言支持
三、被动引用
3.1、通过子类引用父…目录
一、类加载生命周期
二、主动引用
2.1、创建类的实例
2.2、访问类的静态字段或静态方法
2.3、反射
2.4、初始化类的子类时先初始化父类
2.5、虚拟机启动时初始化 main 方法所在的类
2.6、动态语言支持
三、被动引用
3.1、通过子类引用父类的静态字段
3.2、访问编译期常量
3.3、通过数组定义类引用 Java 虚拟机JVM中类的加载并不是随意发生的而是由特定的触发条件决定的。什么时候加载什么时候初始化
这是我们必须要搞清楚的问题尤其在复杂的应用中弄懂类加载的时机能帮助我们避免一些潜在的性能问题和运行时错误。
在本节中我们将详细探讨类加载的时机、主动和被动引用的区别以及常见的类加载触发条件。
一、类加载生命周期
类加载的生命周期包括加载Loading、链接Linking 和 初始化Initialization。而其中初始化阶段是决定类是否被真正加载的关键。
JVM 在什么时候启动类加载过程呢
主要分为主动引用和被动引用两种情况。我们分别看看这两种情况在什么条件下会触发类加载。
二、主动引用
主动引用是指程序显式地使用某个类从而触发类的加载和初始化。根据《Java 虚拟机规范》以下六种情况会触发类的主动引用也就是触发类加载的条件
2.1、创建类的实例
当你使用 new 关键字创建一个类的实例时JVM 会立即加载并初始化该类。
// 触发 MyClass 的加载和初始化
MyClass obj new MyClass();
初始化流程 分配内存给 MyClass 的实例对象。 加载 MyClass 类的字节码并执行静态代码块和静态变量赋值操作。
2.2、访问类的静态字段或静态方法
访问类的静态字段或静态方法时也会触发类的加载和初始化。
// 触发 MyClass 的加载
System.out.println(MyClass.staticVar);
// 触发 MyClass 的加载
MyClass.staticMethod(); 常量不会触发类加载如果静态字段是 final 修饰的常量它在编译期已存入常量池因此不会触发类加载。
System.out.println(MyClass.FINAL_CONSTANT); // 不触发类加载
2.3、反射
通过反射调用类时也会触发类加载。
Class? clazz Class.forName(com.example.MyClass); // 触发 MyClass 的加载
2.4、初始化类的子类时先初始化父类
当初始化一个类时如果它的父类尚未初始化JVM 会先初始化父类。
public class Parent {static {System.out.println(父类初始化);}
}public class Child extends Parent {static {System.out.println(子类初始化);}
}// 先输出父类初始化再输出子类初始化
Child obj new Child();
2.5、虚拟机启动时初始化 main 方法所在的类
虚拟机启动时main 方法所在的类是程序的入口类会被优先加载和初始化。
public static void main(String[] args) {System.out.println(主类加载);
}
2.6、动态语言支持
在 Java 7 引入的 java.lang.invoke 包中当 MethodHandle 最终指向的类需要初始化时也会触发类的加载。
MethodHandle handle MethodHandles.lookup().findStatic(MyClass.class, staticMethod, MethodType.methodType(void.class));
handle.invoke(); // 可能触发 MyClass 的加载
三、被动引用
被动引用不触发类加载。
与主动引用相对被动引用是指访问类的某些特性时不会触发类的加载和初始化。以下是几种典型的被动引用场景。
3.1、通过子类引用父类的静态字段
如果子类只引用父类的静态字段JVM 只会初始化父类而不会初始化子类。
示例
// 只触发 Parent 的加载不触发 Child 的加载
System.out.println(Child.staticVar);
3.2、访问编译期常量
访问 final 修饰的编译期常量不会触发类的加载。
// 不触发 MyClass 的加载
System.out.println(MyClass.FINAL_CONSTANT);
3.3、通过数组定义类引用
通过数组引用一个类不会触发该类的加载。
// 不触发 MyClass 的加载
MyClass[] array new MyClass[10]; 最后为什么需要关注类加载的时机 避免类的过早加载过早加载可能导致不必要的内存消耗尤其在大型应用中。 延迟加载Lazy Loading通过延迟加载可以在真正需要时才加载类减少启动时间。 减少类加载冲突在模块化或插件化的应用中合理安排类加载顺序有助于避免类冲突和类加载死锁问题。