从JVM角度来讲 只有两种类加载器:启动类加载器、其他的类加载器
    因为前者是JVM虚拟机的一部分 后者是独立于JVM实现的
    更细致一点划分 类加载器分为下面三种:
    1)启动类加载器(BootstrapClassLoader)
    启动类加载器是使用C++语言实现的(HotSpot) 负责加载JVM虚拟机运行时所需的基本系统级别的类
    如java.lang.String, java.lang.Object等等
    启动类加载器(Bootstrap Classloader)会读取 {JRE_HOME}/lib 下的jar包(如 rt.jar)和配置 然后将这些系统类加载到方法区内
    由于类加载器是使用平台相关的底层C/C++语言实现的 所以该加载器不能被Java代码访问到
    但是我们可以查询某个类是否被引导类加载器加载过
    2)扩展类加载器 (ExtClassLoader)
    此加载器是java.lang.ClassLoad的子类(不是直接继承) 它负责加载 {JAVA_HOME}\lib\ext 目录下的类库 开发者可以直接获取此加载器
    扩展类加载器是是整个JVM加载器的Java代码可以访问到的类加载器的最顶端 扩展类加载器是没有父级加载器的 即是超级父加载器(此时getParent结果为null)

    3)应用程序类加载器 (AppClassLoader 也叫SystemClassLoader)
    此加载器是java.lang.ClassLoad的子类(不是直接继承)
    此加载器负责加载用户类路径上指定的类库(也就是我们程序员编写的那些java代码)
    若没有指定自定义加载器 则此加载器一般是程序中默认的加载器
    应用程序类加载器将扩展类加载器当成自己的父级加载器
    注意:以上的父加载器和子加载器的关系不是继承关系而是组合关系 子加载器中有一个私有属性 parent 指向父加载器
    J}ZJYIO98}93~}Z~I9WI~Q9.png
    拓展
    用户自定义类加载器(Customized Class Loader)
    用户可以自己定义类加载器来加载类
    所有的类加载器都要继承 java.lang.ClassLoader 类并重写 findClass(String name) 方法
    用户自定义类加载器默认父加载器是 应用程序类加载器
    各个类加载器关系如下:
    双亲委派模型
    双亲委派模型工作过程:
    一个类加载器收到类加载的请求 它首先会把这个请求委派给父级加载器去完成
    如果父级加载器也没有加载 再找父级的父级加载器 层层上升
    只有当父级加载器无法完成此加载请求时 子加载器才会尝试自己去加载
    双亲委派机制好处:
    1)可以防止类的重复加载
    2)可以防止Java核心API类库被篡改
    比如用户自定义一个类加载器 去加载和API类库同名的类
    比如java.lang.Integer 发现该类已被加载
    那么用户指定所要加载的类就不会加载 而是返回已加载过的Integer.class