目录

JVM类加载器

JVM 支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)自定义类加载器(User-Defined ClassLoader)。 所有派生于抽象类 ClassLoader 的类加载器都划分为自定义类加载器。

特点:

  • 启动类加载器,由C++实现,没有父类。
  • 拓展类加载器(ExtClassLoader),由Java语言实现,父类加载器为null
  • 系统类加载器(AppClassLoader),由Java语言实现,父类加载器为ExtClassLoader
  • 自定义类加载器,父类加载器肯定为AppClassLoader。

启动类加载器(引导类加载器,Bootstrap ClassLoader)

  • 这个类加载使用 C/C++ 语言实现,嵌套在 JVM 内部
  • 它用来加载 Java 的核心库(JAVA_HOME/jre/lib/rt.jar、resource.jar或sun.boot.class.path路径下的内容),用于提供 JVM 自身需要的类
  • 并不继承自 java.lang.ClassLoader,没有父加载器
  • 加载扩展类和应用程序类加载器,并指定为他们的父类加载器
  • 出于安全考虑,Bootstrap 启动类加载器只加载名为 java、Javax、sun 等开头的类

扩展类加载器(Extension ClassLoader)

  • Java 语言编写,由 sun.misc.Launcher$ExtClassLoader 实现
  • 派生于 ClassLoader
  • 父类加载器为启动类加载器
  • 从 java.ext.dirs 系统属性所指定的目录中加载类库,或从 JDK 的安装目录的 jre/lib/ext 子目录(扩展目录)下加载类库。如果用户创建的 JAR 放在此目录下,也会自动由扩展类加载器加载

应用程序类加载器(也叫系统类加载器,AppClassLoader)

  • Java 语言编写,由 sun.misc.Lanucher$AppClassLoader 实现
  • 派生于 ClassLoader
  • 父类加载器为扩展类加载器
  • 它负责加载环境变量 classpath 或系统属性 java.class.path 指定路径下的类库
  • 该类加载是程序中默认的类加载器,一般来说,Java 应用的类都是由它来完成加载的
  • 通过 ClassLoader的getSystemClassLoader() 方法可以获取到该类加载器
public static void main(String[] args) {
        //获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);  //sun.misc.Launcher$AppClassLoader@135fbaa4

        //获取其上层:扩展类加载器
        ClassLoader extClassLoader = systemClassLoader.getParent();
        System.out.println(extClassLoader);  //sun.misc.Launcher$ExtClassLoader@2503dbd3

        //再获取其上层:获取不到引导类加载器
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println(bootstrapClassLoader);     //null

        //对于用户自定义类来说,默认使用系统类加载器进行加载,输出和systemClassLoader一样
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader);  //sun.misc.Launcher$AppClassLoader@135fbaa4

        //String 类使用引导类加载器进行加载。Java的核心类库都使用引导类加载器进行加载,所以也获取不到
        ClassLoader classLoader1 = String.class.getClassLoader();
        System.out.println(classLoader1);  //null

        //获取BootstrapClassLoader可以加载的api的路径
        URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
        for (URL url : urls) {
            System.out.println(url.toExternalForm());
        }
    }