JVM 类加载机制深度解析

目录


第一章:类加载概述

1.1 什么是类加载

类加载是 JVM 将字节码文件(.class)加载到内存中,并转换为可以被 JVM 执行的 Class 对象的过程。

1.2 类加载的作用

  1. 字节码验证:确保字节码文件符合 JVM 规范
  2. 内存分配:为类分配内存空间
  3. 符号引用解析:将符号引用转换为直接引用
  4. 初始化:执行类的初始化代码

1.3 类加载的时机

  • 创建类的实例
  • 访问类的静态变量
  • 调用类的静态方法
  • 使用反射访问类
  • 初始化子类时,父类会被加载
  • 虚拟机启动时,包含 main 方法的类会被加载

第二章:类加载过程

2.1 类加载的完整生命周期

类加载过程分为七个阶段:加载验证准备解析初始化使用卸载

java 复制代码
// 类加载过程示例
public class ClassLoadingProcess {
    static {
        System.out.println("静态代码块执行 - 初始化阶段");
    }
    
    private static int staticVar = 10; // 准备阶段分配内存,初始化阶段赋值
    
    public static void main(String[] args) {
        System.out.println("main 方法执行");
        System.out.println("静态变量值: " + staticVar);
    }
}

2.2 加载(Loading)

目的:将字节码文件加载到内存中

过程

  1. 通过类的全限定名获取字节码文件
  2. 将字节码文件转换为方法区的运行时数据结构
  3. 在内存中生成一个代表该类的 Class 对象

代码示例

java 复制代码
// 加载过程演示
public class LoadingDemo {
    public static void main(String[] args) {
        // 通过 Class.forName 显式加载类
        try {
            Class<?> clazz = Class.forName("java.lang.String");
            System.out.println("类加载成功: " + clazz.getName());
            System.out.println("类加载器: " + clazz.getClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

2.3 验证(Verification)

目的:确保字节码文件的正确性和安全性

验证内容

  1. 文件格式验证:验证字节码文件格式
  2. 元数据验证:验证类的元数据信息
  3. 字节码验证:验证字节码指令
  4. 符号引用验证:验证符号引用的正确性

验证示例

java 复制代码
// 验证过程演示
public class VerificationDemo {
    public static void main(String[] args) {
        // 尝试加载一个不存在的类
        try {
            Class<?> clazz = Class.forName("NonExistentClass");
        } catch (ClassNotFoundException e) {
            System.out.println("类不存在,验证失败: " + e.getMessage());
        }
        
        // 尝试加载一个格式错误的类
        try {
            Class<?> clazz = Class.forName("java.lang.String");
            // 验证类的元数据
            System.out.println("类名: " + clazz.getName());
            System.out.println("父类: " + clazz.getSuperclass());
            System.out.println("接口: " + Arrays.toString(clazz.getInterfaces()));
        } catch (Exception e) {
            System.out.println("验证失败: " + e.getMessage());
        }
    }
}

2.4 准备(Preparation)

目的:为类的静态变量分配内存并设置默认值

准备过程

  1. 为静态变量分配内存
  2. 设置默认值(0、false、null)
  3. 为常量分配内存并设置值

准备示例

java 复制代码
// 准备阶段演示
public class PreparationDemo {
    // 准备阶段:分配内存,设置默认值 0
    private static int staticInt;
    
    // 准备阶段:分配内存,设置默认值 false
    private static boolean staticBoolean;
    
    // 准备阶段:分配内存,设置默认值 null
    private static String staticString;
    
    // 准备阶段:分配内存,设置值 100(常量)
    private static final int CONSTANT_INT = 100;
    
    static {
        // 初始化阶段:设置实际值
        staticInt = 10;
        staticBoolean = true;
        staticString = "Hello";
    }
    
    public static void main(String[] args) {
        System.out.println("静态变量值: " + staticInt);
        System.out.println("静态布尔值: " + staticBoolean);
        System.out.println("静态字符串: " + staticString);
        System.out.println("常量值: " + CONSTANT_INT);
    }
}

2.5 解析(Resolution)

目的:将符号引用转换为直接引用

解析内容

  1. 类或接口解析:将类或接口的符号引用转换为直接引用
  2. 字段解析:将字段的符号引用转换为直接引用
  3. 方法解析:将方法的符号引用转换为直接引用
  4. 接口方法解析:将接口方法的符号引用转换为直接引用

解析示例

java 复制代码
// 解析过程演示
public class ResolutionDemo {
    public static void main(String[] args) {
        try {
            // 类解析
            Class<?> clazz = Class.forName("java.lang.String");
            System.out.println("类解析成功: " + clazz.getName());
            
            // 字段解析
            Field field = clazz.getDeclaredField("value");
            System.out.println("字段解析成功: " + field.getName());
            
            // 方法解析
            Method method = clazz.getMethod("length");
            System.out.println("方法解析成功: " + method.getName());
            
            // 接口方法解析
            Class<?> listClass = Class.forName("java.util.List");
            Method listMethod = listClass.getMethod("size");
            System.out.println("接口方法解析成功: " + listMethod.getName());
            
        } catch (Exception e) {
            System.out.println("解析失败: " + e.getMessage());
        }
    }
}

2.6 初始化(Initialization)

目的:执行类的初始化代码

初始化过程

  1. 执行静态代码块
  2. 为静态变量赋值
  3. 执行静态方法

初始化示例

java 复制代码
// 初始化过程演示
public class InitializationDemo {
    // 静态变量
    private static int staticVar = 10;
    
    // 静态代码块
    static {
        System.out.println("静态代码块1执行");
        staticVar = 20;
    }
    
    // 静态代码块
    static {
        System.out.println("静态代码块2执行");
        staticVar = 30;
    }
    
    // 静态方法
    public static void staticMethod() {
        System.out.println("静态方法执行");
    }
    
    public static void main(String[] args) {
        System.out.println("main 方法执行");
        System.out.println("静态变量值: " + staticVar);
        staticMethod();
    }
}

2.7 使用(Using)

目的:类的正常使用阶段

使用过程

  1. 创建类的实例
  2. 调用实例方法
  3. 访问实例变量
  4. 调用静态方法
  5. 访问静态变量

使用示例

java 复制代码
// 使用阶段演示
public class UsingDemo {
    private int instanceVar = 100;
    private static int staticVar = 200;
    
    public UsingDemo() {
        System.out.println("构造函数执行 - 使用阶段");
    }
    
    public void instanceMethod() {
        System.out.println("实例方法执行 - 使用阶段");
        System.out.println("实例变量值: " + instanceVar);
    }
    
    public static void staticMethod() {
        System.out.println("静态方法执行 - 使用阶段");
        System.out.println("静态变量值: " + staticVar);
    }
    
    public static void main(String[] args) {
        System.out.println("=== 使用阶段演示 ===");
        
        // 1. 调用静态方法
        staticMethod();
        
        // 2. 访问静态变量
        System.out.println("访问静态变量: " + staticVar);
        
        // 3. 创建实例
        UsingDemo demo = new UsingDemo();
        
        // 4. 调用实例方法
        demo.instanceMethod();
        
        // 5. 访问实例变量
        System.out.println("访问实例变量: " + demo.instanceVar);
    }
}

2.8 卸载(Unloading)

目的:从内存中移除不再使用的类

卸载条件

  1. 该类的所有实例都已经被回收
  2. 加载该类的 ClassLoader 已经被回收
  3. 该类的 Class 对象没有被任何地方引用

卸载过程

  1. 执行类的清理工作
  2. 释放类占用的内存
  3. 从方法区中移除类的信息

卸载示例

java 复制代码
// 卸载过程演示
public class UnloadingDemo {
    static {
        System.out.println("UnloadingDemo 类加载 - 初始化阶段");
    }
    
    public UnloadingDemo() {
        System.out.println("UnloadingDemo 实例创建 - 使用阶段");
    }
    
    @Override
    protected void finalize() throws Throwable {
        System.out.println("UnloadingDemo 实例被回收 - 卸载阶段");
        super.finalize();
    }
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 卸载过程演示 ===");
        
        // 创建实例
        UnloadingDemo demo = new UnloadingDemo();
        
        // 使用实例
        System.out.println("使用实例: " + demo);
        
        // 释放引用
        demo = null;
        
        // 强制垃圾回收
        System.gc();
        
        // 等待垃圾回收完成
        Thread.sleep(1000);
        
        System.out.println("实例引用已释放,等待垃圾回收");
    }
}

第三章:类加载器体系

3.1 类加载器层次结构

复制代码
Bootstrap ClassLoader (启动类加载器)
    ↓
Extension ClassLoader (扩展类加载器)
    ↓
Application ClassLoader (应用程序类加载器)
    ↓
Custom ClassLoader (自定义类加载器)

3.2 启动类加载器(Bootstrap ClassLoader)

特点

  • 由 C++ 实现,是 JVM 的一部分
  • 负责加载核心类库(rt.jar、charsets.jar 等)
  • 是其他类加载器的父加载器
  • 无法被 Java 程序直接引用

代码示例

java 复制代码
// 启动类加载器演示
public class BootstrapClassLoaderDemo {
    public static void main(String[] args) {
        // 获取核心类库的类加载器
        Class<?> stringClass = String.class;
        ClassLoader stringClassLoader = stringClass.getClassLoader();
        
        System.out.println("String 类的类加载器: " + stringClassLoader);
        System.out.println("String 类的类加载器是否为 null: " + (stringClassLoader == null));
        
        // 获取其他核心类的类加载器
        Class<?> objectClass = Object.class;
        ClassLoader objectClassLoader = objectClass.getClassLoader();
        
        System.out.println("Object 类的类加载器: " + objectClassLoader);
        System.out.println("Object 类的类加载器是否为 null: " + (objectClassLoader == null));
    }
}

3.3 扩展类加载器(Extension ClassLoader)

特点

  • 由 Java 实现
  • 负责加载扩展类库(jre/lib/ext 目录下的 jar 包)
  • 是应用程序类加载器的父加载器

代码示例

java 复制代码
// 扩展类加载器演示
public class ExtensionClassLoaderDemo {
    public static void main(String[] args) {
        // 获取扩展类加载器
        ClassLoader extensionClassLoader = ClassLoader.getSystemClassLoader().getParent();
        
        System.out.println("扩展类加载器: " + extensionClassLoader);
        System.out.println("扩展类加载器类名: " + extensionClassLoader.getClass().getName());
        
        // 获取扩展类加载器的父加载器
        ClassLoader parent = extensionClassLoader.getParent();
        System.out.println("扩展类加载器的父加载器: " + parent);
    }
}

3.4 应用程序类加载器(Application ClassLoader)

特点

  • 由 Java 实现
  • 负责加载应用程序类路径(classpath)下的类
  • 是系统默认的类加载器

代码示例

java 复制代码
// 应用程序类加载器演示
public class ApplicationClassLoaderDemo {
    public static void main(String[] args) {
        // 获取应用程序类加载器
        ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
        
        System.out.println("应用程序类加载器: " + appClassLoader);
        System.out.println("应用程序类加载器类名: " + appClassLoader.getClass().getName());
        
        // 获取当前类的类加载器
        ClassLoader currentClassLoader = ApplicationClassLoaderDemo.class.getClassLoader();
        System.out.println("当前类的类加载器: " + currentClassLoader);
        
        // 验证是否为同一个类加载器
        System.out.println("是否为同一个类加载器: " + (appClassLoader == currentClassLoader));
    }
}

第四章:双亲委派模型

4.1 双亲委派模型原理

双亲委派模型是类加载器的工作机制,确保类的唯一性和安全性。

工作流程

  1. 当类加载器收到类加载请求时,首先委派给父加载器
  2. 如果父加载器无法加载,则由当前加载器加载
  3. 如果当前加载器也无法加载,则抛出 ClassNotFoundException

4.2 双亲委派模型实现

java 复制代码
// 双亲委派模型演示
public class ParentDelegationDemo {
    public static void main(String[] args) {
        // 创建自定义类加载器
        CustomClassLoader customLoader = new CustomClassLoader();
        
        try {
            // 尝试加载 String 类
            Class<?> stringClass = customLoader.loadClass("java.lang.String");
            System.out.println("String 类加载成功: " + stringClass.getName());
            System.out.println("String 类的类加载器: " + stringClass.getClassLoader());
            
            // 尝试加载自定义类
            Class<?> customClass = customLoader.loadClass("ParentDelegationDemo");
            System.out.println("自定义类加载成功: " + customClass.getName());
            System.out.println("自定义类的类加载器: " + customClass.getClassLoader());
            
        } catch (ClassNotFoundException e) {
            System.out.println("类加载失败: " + e.getMessage());
        }
    }
}

// 自定义类加载器
class CustomClassLoader extends ClassLoader {
    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        System.out.println("尝试加载类: " + name);
        
        // 首先检查类是否已经被加载
        Class<?> c = findLoadedClass(name);
        if (c != null) {
            System.out.println("类已加载: " + name);
            return c;
        }
        
        try {
            // 委派给父加载器
            if (getParent() != null) {
                System.out.println("委派给父加载器: " + name);
                c = getParent().loadClass(name);
                if (c != null) {
                    System.out.println("父加载器加载成功: " + name);
                    return c;
                }
            }
        } catch (ClassNotFoundException e) {
            System.out.println("父加载器无法加载: " + name);
        }
        
        // 当前加载器尝试加载
        System.out.println("当前加载器尝试加载: " + name);
        c = findClass(name);
        if (c != null) {
            System.out.println("当前加载器加载成功: " + name);
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
        
        throw new ClassNotFoundException(name);
    }
    
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 这里可以实现自定义的类加载逻辑
        // 例如从网络、数据库等加载类
        throw new ClassNotFoundException(name);
    }
}

4.3 双亲委派模型的优势

  1. 类的唯一性:确保同一个类只被加载一次
  2. 安全性:防止核心类库被恶意替换
  3. 层次性:形成清晰的类加载器层次结构

4.4 双亲委派模型的破坏

破坏场景

  1. SPI 机制:ServiceLoader 使用线程上下文类加载器
  2. OSGi 框架:使用网状类加载器结构
  3. 热部署:需要重新加载类

破坏示例

java 复制代码
// 双亲委派模型破坏示例
public class ParentDelegationBreakDemo {
    public static void main(String[] args) {
        // 使用线程上下文类加载器破坏双亲委派模型
        ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
        
        try {
            // 设置自定义类加载器为上下文类加载器
            CustomClassLoader customLoader = new CustomClassLoader();
            Thread.currentThread().setContextClassLoader(customLoader);
            
            // 使用 ServiceLoader 加载服务
            ServiceLoader<Object> serviceLoader = ServiceLoader.load(Object.class);
            System.out.println("ServiceLoader 使用上下文类加载器: " + 
                Thread.currentThread().getContextClassLoader());
            
        } finally {
            // 恢复原始类加载器
            Thread.currentThread().setContextClassLoader(originalLoader);
        }
    }
}

第五章:类加载时机

5.1 类加载的触发条件

  1. 创建类的实例
  2. 访问类的静态变量
  3. 调用类的静态方法
  4. 使用反射访问类
  5. 初始化子类时,父类会被加载
  6. 虚拟机启动时,包含 main 方法的类会被加载

5.2 类加载时机演示

java 复制代码
// 类加载时机演示
public class ClassLoadingTimingDemo {
    public static void main(String[] args) {
        System.out.println("=== 类加载时机演示 ===");
        
        // 1. 创建类的实例
        System.out.println("\n1. 创建类的实例");
        new InstanceClass();
        
        // 2. 访问类的静态变量
        System.out.println("\n2. 访问类的静态变量");
        System.out.println("静态变量值: " + StaticClass.staticVar);
        
        // 3. 调用类的静态方法
        System.out.println("\n3. 调用类的静态方法");
        StaticClass.staticMethod();
        
        // 4. 使用反射访问类
        System.out.println("\n4. 使用反射访问类");
        try {
            Class<?> clazz = Class.forName("ReflectionClass");
            System.out.println("反射加载类成功: " + clazz.getName());
        } catch (ClassNotFoundException e) {
            System.out.println("反射加载类失败: " + e.getMessage());
        }
        
        // 5. 初始化子类时,父类会被加载
        System.out.println("\n5. 初始化子类时,父类会被加载");
        new ChildClass();
    }
}

// 实例类
class InstanceClass {
    static {
        System.out.println("InstanceClass 静态代码块执行");
    }
    
    public InstanceClass() {
        System.out.println("InstanceClass 构造函数执行");
    }
}

// 静态类
class StaticClass {
    static {
        System.out.println("StaticClass 静态代码块执行");
    }
    
    public static int staticVar = 10;
    
    public static void staticMethod() {
        System.out.println("StaticClass 静态方法执行");
    }
}

// 反射类
class ReflectionClass {
    static {
        System.out.println("ReflectionClass 静态代码块执行");
    }
}

// 父类
class ParentClass {
    static {
        System.out.println("ParentClass 静态代码块执行");
    }
}

// 子类
class ChildClass extends ParentClass {
    static {
        System.out.println("ChildClass 静态代码块执行");
    }
}

第六章:自定义类加载器

6.1 自定义类加载器实现

java 复制代码
// 自定义类加载器实现
public class CustomClassLoader extends ClassLoader {
    private String classPath;
    
    public CustomClassLoader(String classPath) {
        this.classPath = classPath;
    }
    
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            // 读取类文件
            byte[] classData = loadClassData(name);
            if (classData != null) {
                // 定义类
                return defineClass(name, classData, 0, classData.length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        throw new ClassNotFoundException(name);
    }
    
    private byte[] loadClassData(String name) throws IOException {
        String fileName = name.replace('.', '/') + ".class";
        String fullPath = classPath + "/" + fileName;
        
        try (FileInputStream fis = new FileInputStream(fullPath);
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }
            return baos.toByteArray();
        }
    }
}

6.2 自定义类加载器使用示例

java 复制代码
// 自定义类加载器使用示例
public class CustomClassLoaderDemo {
    public static void main(String[] args) {
        try {
            // 创建自定义类加载器
            CustomClassLoader customLoader = new CustomClassLoader("src");
            
            // 加载自定义类
            Class<?> clazz = customLoader.loadClass("CustomClass");
            System.out.println("类加载成功: " + clazz.getName());
            System.out.println("类加载器: " + clazz.getClassLoader());
            
            // 创建实例
            Object instance = clazz.newInstance();
            System.out.println("实例创建成功: " + instance);
            
        } catch (Exception e) {
            System.out.println("自定义类加载失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

// 自定义类
class CustomClass {
    static {
        System.out.println("CustomClass 静态代码块执行");
    }
    
    public CustomClass() {
        System.out.println("CustomClass 构造函数执行");
    }
    
    public void sayHello() {
        System.out.println("Hello from CustomClass!");
    }
}

第七章:类加载实战演示

7.1 完整的类加载演示

java 复制代码
// 完整的类加载演示
public class ClassLoadingCompleteDemo {
    public static void main(String[] args) {
        System.out.println("=== JVM 类加载机制完整演示 ===\n");
        
        // 1. 类加载器层次结构演示
        demonstrateClassLoaderHierarchy();
        
        // 2. 双亲委派模型演示
        demonstrateParentDelegation();
        
        // 3. 类加载过程演示
        demonstrateClassLoadingProcess();
        
        // 4. 自定义类加载器演示
        demonstrateCustomClassLoader();
        
        // 5. 类加载时机演示
        demonstrateClassLoadingTiming();
    }
    
    /**
     * 演示类加载器层次结构
     */
    private static void demonstrateClassLoaderHierarchy() {
        System.out.println("=== 类加载器层次结构演示 ===");
        
        // 获取当前类的类加载器
        ClassLoader currentLoader = ClassLoadingCompleteDemo.class.getClassLoader();
        System.out.println("当前类的类加载器: " + currentLoader);
        
        // 获取父加载器
        ClassLoader parent = currentLoader.getParent();
        System.out.println("父加载器: " + parent);
        
        // 获取祖父加载器
        ClassLoader grandparent = parent.getParent();
        System.out.println("祖父加载器: " + grandparent);
        
        // 获取核心类的类加载器
        ClassLoader stringLoader = String.class.getClassLoader();
        System.out.println("String 类的类加载器: " + stringLoader);
        
        System.out.println();
    }
    
    /**
     * 演示双亲委派模型
     */
    private static void demonstrateParentDelegation() {
        System.out.println("=== 双亲委派模型演示 ===");
        
        try {
            // 尝试加载核心类
            Class<?> stringClass = Class.forName("java.lang.String");
            System.out.println("String 类加载成功: " + stringClass.getName());
            System.out.println("String 类的类加载器: " + stringClass.getClassLoader());
            
            // 尝试加载扩展类
            Class<?> listClass = Class.forName("java.util.List");
            System.out.println("List 接口加载成功: " + listClass.getName());
            System.out.println("List 接口的类加载器: " + listClass.getClassLoader());
            
        } catch (ClassNotFoundException e) {
            System.out.println("类加载失败: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    /**
     * 演示类加载过程
     */
    private static void demonstrateClassLoadingProcess() {
        System.out.println("=== 类加载过程演示 ===");
        
        try {
            // 加载类
            Class<?> clazz = Class.forName("ClassLoadingProcessDemo");
            System.out.println("类加载成功: " + clazz.getName());
            
            // 创建实例
            Object instance = clazz.newInstance();
            System.out.println("实例创建成功: " + instance);
            
        } catch (Exception e) {
            System.out.println("类加载过程演示失败: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    /**
     * 演示自定义类加载器
     */
    private static void demonstrateCustomClassLoader() {
        System.out.println("=== 自定义类加载器演示 ===");
        
        try {
            // 创建自定义类加载器
            CustomClassLoader customLoader = new CustomClassLoader("src");
            
            // 加载类
            Class<?> clazz = customLoader.loadClass("CustomClass");
            System.out.println("自定义类加载成功: " + clazz.getName());
            System.out.println("自定义类的类加载器: " + clazz.getClassLoader());
            
        } catch (Exception e) {
            System.out.println("自定义类加载器演示失败: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    /**
     * 演示类加载时机
     */
    private static void demonstrateClassLoadingTiming() {
        System.out.println("=== 类加载时机演示 ===");
        
        // 访问静态变量
        System.out.println("访问静态变量: " + TimingDemo.staticVar);
        
        // 调用静态方法
        TimingDemo.staticMethod();
        
        // 创建实例
        new TimingDemo();
        
        System.out.println();
    }
}

// 类加载过程演示类
class ClassLoadingProcessDemo {
    static {
        System.out.println("ClassLoadingProcessDemo 静态代码块执行");
    }
    
    public ClassLoadingProcessDemo() {
        System.out.println("ClassLoadingProcessDemo 构造函数执行");
    }
}

// 类加载时机演示类
class TimingDemo {
    static {
        System.out.println("TimingDemo 静态代码块执行");
    }
    
    public static int staticVar = 100;
    
    public static void staticMethod() {
        System.out.println("TimingDemo 静态方法执行");
    }
    
    public TimingDemo() {
        System.out.println("TimingDemo 构造函数执行");
    }
}

总结

JVM 类加载机制关键要点

  1. 类加载完整生命周期:加载 → 验证 → 准备 → 解析 → 初始化 → 使用 → 卸载
  2. 类加载器体系:启动类加载器 → 扩展类加载器 → 应用程序类加载器 → 自定义类加载器
  3. 双亲委派模型:确保类的唯一性和安全性
  4. 类加载时机:创建实例、访问静态成员、反射、初始化子类等
  5. 使用阶段:类的正常使用,包括实例创建、方法调用、变量访问等
  6. 卸载阶段:类的内存回收,需要满足三个条件才能被卸载
  7. 自定义类加载器:实现热部署、类隔离等功能

类加载机制的重要性

  • 安全性:防止核心类库被恶意替换
  • 唯一性:确保同一个类只被加载一次
  • 灵活性:支持自定义类加载逻辑
  • 性能:通过缓存和委派机制提高加载效率

通过深入理解 JVM 类加载机制,我们可以更好地理解 Java 程序的运行原理,也能在需要时实现自定义的类加载逻辑。

相关推荐
安逸sgr4 小时前
SpringMVC启动流程
java·jvm·spring·spring cloud·eclipse·tomcat·maven
修行者Java1 天前
JVM 内存结构
jvm
代码程序猿RIP1 天前
【SQLite 库】sqlite3_open_v2
jvm·oracle·sqlite
柳贯一(逆流河版)2 天前
Spring Boot Actuator+Micrometer:高并发下 JVM 监控体系的轻量化实践
jvm·spring boot·后端
lpruoyu3 天前
颜群JVM【04】助记符
jvm
Flash Dog3 天前
【JVM】——实战篇
jvm
DKPT3 天前
JVM栈溢出和堆溢出哪个先满?
java·开发语言·jvm·笔记·学习
m0_475064503 天前
jvm双亲委派的含义
java·jvm
胡小禾3 天前
JDK17和JDK8的 G1
jvm·算法