jvm2之类加载器

134 阅读2分钟

前言

今天是学习jvm第二天,是关于类加载子系统的一些内容,因为康师傅现在对类加载子系统并不打算仔细讲解,所以以下是一些类加载器的内容。

加载器:

  1. 从概念上来讲,自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范却没有这么定义,而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器。在康师傅的视频里,扩展类加载器和应用类加载器都被称作自定义类加载器。说是官网定义。
  2. 无论类加载器的类型如何划分,在程序中我们最常见的类加载器始终只有3个,如下所示
  • 引导类加载器,又叫做启动类加载器(Bootstrap ClassLoader)

    • 他加载的就是Java的核心类库中的类,例如:jre\lib\rt.jar、resource.jar、或sun.boot.class.path路径下。他只加载包名为java、javax、sun等开头的类。
    • 这个类加载器是用c\c++实现的,嵌套在JVM内部。
    • 是下面两个加载器的父加载器
    •     jre/lib/resources.jar
          jre/lib/rt.jar
          jre/lib/sunrsasign.jar
          jre/lib/jsse.jar
          jre/lib/jce.jar
          jre/lib/charsets.jar
          jre/lib/jfr.jar
          jre/classes
      
  • 扩展类加载器(Extension ClassLoader)

    • 加载的是位于jre\lib\ext子目录下的类。
    • 如果用户自己创建的JAR放在此目录下,也会自动由此加载器加载。
    • 是java是实现的,在java中的具体实现是ExtClassLoader
    • 父加载器是启动类加载器
    •   jre\lib\ext
        C:\Windows\Sun\Java\lib\ext
      
  • 应用类加载器,又叫做系统类加载器(System ClassLoader)

    • 加载的是classpath路径下的类。也就是我们自己在程序中编写的类使用此加载器加载。
    • 也是java是实现的,在java中的具体实现是AppClassLoader
    • 父加载器是扩展类加载器

下面是一些代码示例

//sun.misc.Launcher$AppClassLoader@18b4aac2,这是应用类(系统类)加载器,
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
​
​
//sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
System.out.println(contextClassLoader);
​
​
//sun.misc.Launcher$AppClassLoader@18b4aac2
System.out.println(myTest.class.getClassLoader());
//获取到的都是应用类加载器
​
​
//null,因为启动类加载器是非java编写,是获取不到的。
System.out.println(String.class.getClassLoader)
                   
                   
//sun.misc.Launcher$ExtClassLoader@28a418fc,扩展类加载器
System.out.println(systemClassLoader.getParent());    

在了解了三个类加载器,并且直到谁是谁的父类加载器之后,来简单说一下双亲委派机制

下面是双亲委派机制的流程

1.当一个类收到了类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器去完成。

2.如果父类加载器还有父类加载器,则进一步向上委托。

3.如果父类加载器无法完成加载任务,子类才会尝试自己加载。