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 程序的运行原理,也能在需要时实现自定义的类加载逻辑。

相关推荐
代码栈上的思考1 天前
JVM中内存管理的策略
java·jvm
thginWalker1 天前
深入浅出 Java 虚拟机之进阶部分
jvm
沐浴露z1 天前
【JVM】详解 线程与协程
java·jvm
thginWalker1 天前
深入浅出 Java 虚拟机之实战部分
jvm
程序员卷卷狗3 天前
JVM 调优实战:从线上问题复盘到精细化内存治理
java·开发语言·jvm
Sincerelyplz3 天前
【JDK新特性】分代ZGC到底做了哪些优化?
java·jvm·后端
初学小白...4 天前
线程同步机制及三大不安全案例
java·开发语言·jvm
凤山老林4 天前
还在用JDK8?JDK8升级JDK11:一次价值千万的升级指南
java·开发语言·jvm·spring boot·后端·jdk
2501_938790074 天前
详解 JVM 中的对象创建过程:类加载检查、内存分配、初始化的完整流程
jvm
宸津-代码粉碎机4 天前
Java内部类内存泄露深度解析:原理、场景与根治方案(附GC引用链分析)
java·开发语言·jvm·人工智能·python