Skip to content

[!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
null

JVM 的类加载机制

全盘负责

当一个类加载器负责加载某个 Class 时,该 Class 所依赖和引用的其他 Class 也将由该类加载器负责载入(除非显式使用另一个类加载器来载入)

父类委托

当一个类加载器负责加载某个 Class 时,先让父类加载器试图加载该 Class,只有在父类加载器无法加载该类时,才尝试从自己的类路径中加载该类

缓存机制

保证所有加载过的 Class 都会被缓存,当程序需要使用某个 Class 对象时,类加载器先从缓存区中搜索该 Class。只有当缓存区中不存在该 Class 对象时,系统才会读取该类对应的二进制数据,并将其转换为 Class 对象,存储到缓存区