[!quote] 类加载 如果程序要使用某个类,该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化
类加载的三个步骤
类的加载 :将 class 文件读入内存,并为之创建一个 java.lang.Class 对象
类的连接 :
- 验证阶段:检验被加载的类是否有正确的内部结构,并和其他类协调一致
- 准备阶段:为类变量分配内存,并设置默认初始化值
- 解析阶段:将类的二进制数据中的符号引用替换为直接引用
类的初始化 :主要对类变量进行初始化
[!hint] 特点
- 如果该类未被加载/连接,则先加载/连接
- 如果该类的父类还未被初始化,则先初始化其父类【
所以被最先初始化的类一定是 Object 类】- 如果类中有初始化语句,则系统依次执行这些初始化语句
[!hint] 什么时候类会初始化 ?
- 创建类的实例
- 调用类的类方法【静态方法】
- 访问类/接口的类变量【静态变量】
- 为类变量赋值
- 初始化某个类的子类
- 直接使用
java.exe命令来运行某个主类【包含 main 方法的类】- 使用反射方式来强制创建某个类/接口对应的
java.lang.Class对象
类加载器
类加载器负责将 .class 文件加载到内存中,并为之生成对应的 java.lang.Class 对象
ClassLoader getSystemClassLoader()ClassLoader getParent()
Java 运行时具有以下内置类加载器 :
- Bootstrap class loader :是虚拟机的内置类加载器,通常表示为
null,并且没有父类 - Platform class loader :平台类加载器负责加载平台类【Java SE 平台 API、其实现类和特定于 JDK 的运行时类】
- System class loader :被称为应用程序类加载器,通常用于定义应用程序类路径、模块路径和特定于 JDK 的工具上的类
java
public static void main(String[] args) {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
ClassLoader parentParent = parent.getParent(); //默认为null
System.out.println(parentParent);
}
jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
jdk.internal.loader.ClassLoaders$PlatformClassLoader@448139f0
nullJVM 的类加载机制
全盘负责
当一个类加载器负责加载某个 Class 时,该 Class 所依赖和引用的其他 Class 也将由该类加载器负责载入(除非显式使用另一个类加载器来载入)
父类委托
当一个类加载器负责加载某个 Class 时,先让父类加载器试图加载该 Class,只有在父类加载器无法加载该类时,才尝试从自己的类路径中加载该类
缓存机制
保证所有加载过的 Class 都会被缓存,当程序需要使用某个 Class 对象时,类加载器先从缓存区中搜索该 Class。只有当缓存区中不存在该 Class 对象时,系统才会读取该类对应的二进制数据,并将其转换为 Class 对象,存储到缓存区