Java 类加载

本文将介绍 Java 类的加载、连接与初始化。

一、类的加载、连接与初始化

1. 何时进行类的加载、连接与初始化?

  • 当程序需要使用某个类时
  • 当使用预加载机制时

2. 类的加载

类加载是指将类的 class 文件读入内存,并为之创建一个 Java.lang.Class 对象。

Java 中的所有类其实也是实例,它们是 Java.lang.Class 类的实例。

3. 类的连接

连接阶段负责将类的二进制数据合并到 JRE 中,可以分为以下三个阶段:

  • 验证阶段:校验被加载的类是否有正确的内部结构,并与其它类协调一致
  • 准备阶段:为类的类变量分配内存,并置零
  • 解析阶段:将类的二进制数据中的符号引用替换为直接引用

4. 类的初始化

可以分为以下几个步骤:

  • 假如类的直接父类还没有初始化,加载、连接并初始化该直接父类

  • 对类进行初始化,主要就是对类变量进行初始化

    为类变量指定初始化值的方法:

    • 在声明类变量时指定初始值
    • 使用静态初始化块为类变量指定初始化值

二、类加载器

1. 什么是类加载器?

类加载器负责将 .class 文件加载到内存中,并生成对应的 Java.lang.Class 对象。

2. 类加载机制

(1) 类的唯一标识

当类已经被加载之后,就不应当再次载入。正如一个对象有一个唯一的标识一样,一个载入 JVM 的类也有唯一的标识

在 Java 中,类用全限定类名作为标识,在 JVM 中,类用全限定类名及其类加载器作为标识。

这意味着,一个类可以被多个类加载器加载,它们会被视为不同的类。

(2) 类加载机制

  • 全盘负责:当一个类加载器负责加载某个 Class 时,该 Class 所依赖的和引用的其它 Class 也将由该加载器负责载入,除非显性使用另外的类加载器来载入
  • 父类委托:先让父类加载器试图加载,只有在父类加载器无法加载时,才尝试从自己的类路径加载该 Class
  • 缓存机制:保证所有加载过的 Class 都会被缓存,当程序中需要使用某个 Class 时,先从缓存区中搜寻该 Class,只有当缓存区中不存在该 Class 时,才会进行加载

3. 内置类加载器

Java 运行时具有以下内置类加载器:

  • Bootstrap ClassLoader:根类加载器,负责加载 Java 核心类

    Java 核心类:包以 Java 开头

  • Extension ClassLoader:扩展类加载器,负责加载 Java 扩展类

    Java 扩展类:包以 Javax 开头

  • App ClassLoader:系统类加载器,又被称为应用程序类加载器,负责加载用户路径上所指定的类库

参考