Java类加载器

Java类加载器(Class Loader)是Java虚拟机(JVM)的一部分,负责将编译后的Java字节码加载到JVM中并解析为可执行的Java类。类加载器是Java中重要的概念之一,它提供了动态加载类的能力,使得Java应用程序可以在运行时加载和使用编译时不存在的类。

类加载器的作用

类加载器的主要作用是将类的字节码加载到JVM中并转化为Java类。在Java应用程序运行过程中,当需要使用某个类时,JVM会先检查该类是否已经加载,如果没有加载则会使用类加载器将其加载到JVM中。

类加载器的主要任务包括:

  1. 加载:通过类的全限定名(Fully Qualified Name)查找并加载对应的字节码文件。
  2. 验证:校验加载的字节码文件是否符合Java语言的规范,例如文件格式是否正确、安全性检查等。
  3. 准备:为类的静态变量分配内存空间,并设置默认值。
  4. 解析:将类或接口的二进制名称解析为对应的引用,例如将类的全限定名解析为JVM内部的表示形式。
  5. 初始化:执行类的初始化代码,包括静态变量赋值、静态代码块等。
  6. 使用:类加载完成后,可以通过其创建对象、调用方法等操作。

类加载器的层次结构

Java类加载器的层次结构如下所示:

classDiagram
    class ClassLoader
    ClassLoader <|-- BootstrapClassLoader
    ClassLoader <|-- ExtensionClassLoader
    ClassLoader <|-- ApplicationClassLoader
    ClassLoader <|-- CustomClassLoader
  • BootstrapClassLoader(启动类加载器):负责加载JVM本身所需要的类库,例如rt.jar等。
  • ExtensionClassLoader(扩展类加载器):负责加载JVM的扩展类库,例如ext目录下的JAR文件。
  • ApplicationClassLoader(应用程序类加载器):负责加载应用程序的类,例如classpath下的类。
  • CustomClassLoader(自定义类加载器):开发者可以通过继承ClassLoader类实现自己的类加载器。

类加载器之间通过双亲委派(Parent Delegation)模型进行加载,即当一个类加载器需要加载某个类时,它会先将该请求委派给父加载器进行加载,只有父加载器无法加载时才由子加载器尝试加载。这种机制可以保证Java核心类库的安全性,并避免类的重复加载。

下面是一个示例代码,演示了类加载器的层次结构:

public class ClassLoaderDemo {
    public static void main(String[] args) {
        ClassLoader classLoader = ClassLoaderDemo.class.getClassLoader();
        System.out.println("ClassLoader: " + classLoader);
        System.out.println("Parent ClassLoader: " + classLoader.getParent());
        System.out.println("Grandparent ClassLoader: " + classLoader.getParent().getParent());
    }
}

输出结果为:

ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@70dea4e
Parent ClassLoader: jdk.internal.loader.ClassLoaders$PlatformClassLoader@5c647e05
Grandparent ClassLoader: null

从输出结果可以看出,ClassLoaderDemo类使用的是应用程序类加载器(ApplicationClassLoader),其父加载器是扩展类加载器(ExtensionClassLoader),扩展类加载器的父加载器是启动类加载器(BootstrapClassLoader)。

类加载器的使用

类加载器的使用非常简单,只需要使用ClassLoader类的loadClass方法即可加载指定类。下面是一个示例代码,演示了如何使用类加载器加载类:

public class ClassLoaderExample {
    public static void main(String[] args) throws ClassNotFoundException {
        // 使用BootstrapClassLoader加载类
        ClassLoader bootstrapClassLoader = null;
        Class<?> bootstrapClass = bootstrapClassLoader.loadClass("java.lang.String");
        System.out.println("BootstrapClassLoader: " + bootstrapClass.getClassLoader());

        // 使用ExtensionClassLoader加载类
        ClassLoader extensionClassLoader = ClassLoaderExample.class.getClassLoader().getParent();
        Class<?> extensionClass = extensionClassLoader.loadClass("com.example.MyClass");
        System.out.println("ExtensionClassLoader: " + extensionClass.getClassLoader