# Java类加载机制

Java类加载机制(Class Loading Mechanism)是Java虚拟机(JVM)将Java类的字节码文件.class文件)加载到内存中的过程,并为其创建对应的Class对象。类加载机制是Java运行时的核心功能之一,确保类在被使用之前被正确加载、连接和初始化。

Java的类加载机制采用了动态加载(按需加载)和双亲委派模型来管理类的加载顺序和安全性。

# 一、Java类加载的基本流程

Java的类加载过程分为以下几个阶段:

  1. 加载(Loading)
  2. 连接(Linking)
    • 验证(Verification)
    • 准备(Preparation)
    • 解析(Resolution)
  3. 初始化(Initialization)

# 1. 加载(Loading)

在类加载阶段,JVM会通过类加载器找到 .class 文件,并将它的字节码读入内存,生成对应的 Class 对象。这一步主要完成以下操作:

  • 通过类的全限定名(如 com.example.MyClass)来定位该类的字节码文件。
  • 使用类加载器读取字节码文件,并生成 Class 对象。
  • 将类的静态数据结构存储在内存的方法区中。

# 2. 连接(Linking)

连接阶段是将类的二进制数据合并到 JVM 的运行时环境中,分为三个子阶段:

  • 验证(Verification):确保类的字节码符合JVM的规范,防止恶意字节码攻击。
  • 准备(Preparation):为类的静态变量分配内存,并将它们初始化为默认值(如 int 类型的默认值为 0,引用类型为 null)。
  • 解析(Resolution):将类的符号引用(常量池中的符号)替换为直接引用(具体内存地址)。这一步是将符号链接解析为可以被程序直接访问的内存地址。

# 3. 初始化(Initialization)

初始化阶段是类加载过程的最后阶段,它会执行类的静态初始化块(static 块)和为静态变量赋予初始值。这一步是在类首次主动使用时进行的。

注意:类在初始化时才会执行其静态块和静态变量的初始化,加载阶段仅仅是将类信息加载到内存中,不会执行任何代码。

# 二、双亲委派模型

Java的类加载机制遵循双亲委派模型(Parent Delegation Model),即每个类加载器在加载一个类时,首先会把类加载请求委托给其父加载器。如果父加载器无法完成类的加载任务,才会尝试自己加载。

# 双亲委派的基本流程:

  1. 类加载器接收到类加载请求。
  2. 将加载请求委派给父类加载器,递归向上,直至根类加载器。
  3. 如果父类加载器能够加载该类,则加载成功;否则由当前类加载器进行加载。

# 类加载器的分类:

  • Bootstrap ClassLoader(引导类加载器):负责加载<JAVA_HOME>/lib目录下的核心类库,如 rt.jar。这是最顶层的类加载器,通常由C++实现,不属于 java.lang.ClassLoader 的子类。
  • Extension ClassLoader(扩展类加载器):负责加载扩展目录下的类库,如<JAVA_HOME>/lib/ext目录中的类。
  • Application ClassLoader(应用类加载器):负责加载用户类路径(CLASSPATH)下的类。这个加载器是最常用的,加载应用程序的类。

# 双亲委派模型的优点:

  • 安全性:通过双亲委派,核心类库只能由引导类加载器加载,防止应用程序类加载器加载核心类并篡改。
  • 避免重复加载:类加载器总是先委托给父类加载器,避免同一个类被加载多次,确保类的唯一性。

# 三、类加载器的分类

Java中类加载器分为以下几种类型:

# 1. 启动类加载器(Bootstrap ClassLoader)

  • 这是最顶层的类加载器,负责加载Java核心类库(例如rt.jar)。
  • 它是由JVM自带的,并不是ClassLoader的子类,通常由本地代码(C/C++)实现。

# 2. 扩展类加载器(Extension ClassLoader)

  • 负责加载<JAVA_HOME>/lib/ext目录下的类库,或者由系统变量java.ext.dirs指定的路径中的类。
  • 它是ClassLoader类的子类。

# 3. 应用程序类加载器(Application ClassLoader)

  • 负责加载应用程序的类路径(CLASSPATH)中的类文件。
  • 它也是ClassLoader类的子类,是我们开发中最常接触的类加载器。

# 4. 自定义类加载器

  • 用户可以通过继承ClassLoader类并重写findClass()方法,来实现自定义类加载器。自定义类加载器可以加载远程的类、加密的类文件等。

# 四、类加载的时机

类的加载并不是立即发生的,而是按需进行。当且仅当类首次主动使用时,才会触发类的加载和初始化。

以下几种情况会触发类的初始化:

  1. 创建类的实例(如 new 操作)。
  2. 访问类的静态变量或调用静态方法。
  3. 反射操作(如 Class.forName())。
  4. 初始化子类时,父类也会被初始化。
  5. Java虚拟机启动时会先初始化主类(包含 main 方法的类)。

# 五、类的加载顺序

  1. 父类的静态块先于子类的静态块执行。
  2. 父类的静态变量先于子类的静态变量初始化。
  3. 父类的实例变量先于子类的实例变量初始化。
  4. 父类的构造方法先于子类的构造方法执行。

# 六、类加载的特点

  1. 按需加载:Java类是在首次使用时才会加载,而不是在程序启动时全部加载。
  2. 一次加载:类只会加载一次,在JVM中形成唯一的Class对象,避免重复加载同一个类。

# 七、类卸载

类的卸载发生在类加载器不再使用,且该类的所有对象都不可达时。Java类的卸载非常罕见,通常JVM不会主动卸载类。通过自定义类加载器和热部署技术,可以在应用服务器中实现类的动态卸载。

# 八、示例:自定义类加载器

下面是一个自定义类加载器的简单实现,通过它可以加载指定目录下的类文件:

import java.io.*;

public class CustomClassLoader extends ClassLoader {
    
    private String classPath;
    
    public CustomClassLoader(String classPath) {
        this.classPath = classPath;
    }
    
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classData = loadClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        } else {
            return defineClass(name, classData, 0, classData.length);
        }
    }

    private byte[] loadClassData(String className) throws ClassNotFoundException {
        String fileName = classPath + className.replace(".", "/") + ".class";
        try {
            InputStream inputStream = new FileInputStream(fileName);
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            int nextValue = 0;
            while ((nextValue = inputStream.read()) != -1) {
                byteStream.write(nextValue);
            }
            return byteStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            throw new ClassNotFoundException("Class not found in path: " + classPath);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 总结

Java的类加载机制通过双亲委派模型和类加载器实现了按需加载、类隔离和安全性保障。了解类加载的流程和原理可以帮助开发者调试类加载问题(如类冲突、重复加载),并通过自定义类加载器来实现动态加载、插件化开发等高级功能。

最近更新: 9/24/2024, 10:36:04 PM
备案号:粤ICP备2023124211号-1
Copyright © 2023-2024 StarChenTech All Rights Reserved.