Skip to content

类加载器(Class Loader)

简介

类加载器(Class Loader)是 Java 虚拟机(JVM)的一部分,负责将类的字节码加载到 JVM 中,并转换成可以执行的 Java 类。

分类

  • 引导类加载器(Bootstrap ClassLoader)
  • 自定义类加载器(User-Defined ClassLoader)

image-20230629002924702

引导类加载器

  • 该类加载器使用 C++ 语言实现,是虚拟机自身的一部分
    • 仅限 HotSpot,有部分 Java 虚拟机,整个虚拟机都是 Java 编写的,Bootstrap ClassLoader 也是使用 Java 语言编写的。
    • 因为是 C++ 语言实现,所有在 Java 中获取该加载器的时候为 null,都不是同一个编程语言,当然不属于 Java 中的对象的概念,但是并不是指没有该类加载器

自定义类加载器

  • 所有派生于 ClassLoader 的类加载器,都属于自定义类加载器
    • 不同 JDK 版本,不管是 ExtClassLoader 还是 AppClassLoader 或者是 PlatformClassLoader 或者其他的类加载器,都派生于 ClassLoader
    • JDK8 中:ExtClassLoader 和 AppClassLoader 是 Launcher 内部类,
    • JDK17 中:PlatformClassLoader 和 AppClassLoader 是 ClassLoaders 内部类,

测试

java
public class TestClassLoader {

    public static void main(String[] args) {
        Class<TestClassLoader> aClass = TestClassLoader.class;

        //这里为了符合打印的顺序,符合双亲委派逻辑图的顺序
        System.out.println(aClass.getClassLoader().getParent().getParent());	//获取该类的类加载器的父级的父级(启动类/引导类加载器)
        System.out.println(aClass.getClassLoader().getParent());				//获取该类的类加载器的父级(不是父类)
        System.out.println(aClass.getClassLoader());							//获取该类的类加载器
    }

}
java
//在 JDK8 中执行结果 
null
sun.misc.Launcher$ExtClassLoader@4554617c
sun.misc.Launcher$AppClassLoader@18b4aac2
java
//在 JDK11 中执行结果
null
jdk.internal.loader.ClassLoaders$PlatformClassLoader@7c30a502
jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
java
//在 JDK17 中执行结果
null
jdk.internal.loader.ClassLoaders$PlatformClassLoader@511baa65
jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b

作用

  • 引导类加载器

    • 加载 Java 核心库,用于提供 JVM 自身需要的类,为了安全考虑,只加载部门包名为 java、javax、sun 开头的类
    • 加载 ExtClassLoader、AppClassLoader、PlatformClassLoader
  • ExtClassLoader(JDK 8)

  • PlatformClassLoader(JDK 17)

  • AppClassLoader

    • 该类是程序中默认的类加载器,一般情况,都是由该类完成加载

    • java
      //获取系统类加载器
      System.out.println(ClassLoader.getSystemClassLoader());

自定义类加载器

  • 一般情况,以上三种类加载器足够使用了,肯定有特殊情况不够用,哪些情况需要用户自定义类加载器呢?
    • 隔离加载类
    • 修改加载方式
    • 扩展加载源
    • 防止源码泄露

如何自定义类加载器

双亲委派模型(Parents Delegation Model)

图中的箭头不是表示父类关系,很多程序员当成 Java 中的 extends 继承关系了,这是错的,

图中的箭头只是为了表示委派关系

双亲委派模型在 JDK1.2 期间被引入,但不是强制性的约束,而是 Java 设计者推荐给开发者的一种实现方式,后续会讲到破坏双亲委派模型的情况。

破坏双亲委派