抛开源码谈双亲委派

public class Test {
    public static void main(String[] args) {

        System.out.println(Test.class.getClassLoader());
        System.out.println(Test.class.getClassLoader().getParent());
        System.out.println(Test.class.getClassLoader().getParent().getParent());
    }
}

打印结果:

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1a6c5a9e
null

       第一行打印的是 AppClassLoader 应用类加载器,它的父类加载器是 ExtClassLoader(Ext 是 Extension的缩写)扩展类加载器,但 Ext 加载器的父类打印出来却是个 null,这是因为 启动类加载器(null)并不是 java 实现的。

一、类加载器

  1. 启动类加载器(BootstrapClassLoader):加载 java 的核心类库

  2. 扩展类加载器(ExtClassLoader ):加载 java 扩展类库

  3. 应用类加载器(AppClassLoader):加载 环境变量 classpath 下面的类

  4. 自定义类加载器(暂且忽略)

二、什么是双亲委派?

       双亲委派机制是指当一个类加载器收到一个类加载请求时,该类加载器首先会把请求委派给父类加载器,当父类加载器在自己的搜索范围内找不到指定类时,子类加载器才会尝试自己去加载,如果子类加载器范围内也找不到该类,则会报 ClassNotFoundException。

      通俗来讲,就是当要加载一个类时,

  1. 首先 AppClassLoader 会收到加载请求,但它不会直接加载这个类,而是把这个加载请求抛给它的父类加载器:ExtClassLoader ;
  2. 而 ExtClassLoader 收到类加载请求时,也不会直接加载这个类,而是又把这个加载请求抛给它的父类加载器:BootstrapClassLoader;
  3. BootstrapClassLoader 收到类加载请求后,则会在它的范围内寻找这个类,如果找到了,就直接加载,如果找不到,就把加载请求又朝它的子类加载器:ExtClassLoader 丢过去;
  4. ExtClassLoader 收到父类丢过来的类加载请求,就会在自己管辖范围内寻找这个类,德行跟它的父类一样,找到就加载,找不到就 抛出个异常 给子类加载器:AppClassLoader;
  5. AppClassLoader 收到父类丢过来的类加载请求后... 发现祖父和父亲都找不到这个类,就会自己尝试去加载,德行也是遗传的,找到就加载,找不到也会抛异常:ClassNotFoundException ,这个异常的意思是:在系统整个 java 的运行环境中,都找不到这个类。

       在这里 ExtClassLoader 找不到会给 AppClassLoader 抛异常,而 BootstrapClassLoader 找不到并不会给 ExtClassLoader 抛异常,也是因为 BootstrapClassLoader 并不是 java 实现的。

--- BootstrapClassLoader 为什么不是 java 实现的?

     因为启动类加载器非常重要,它要把整个 java 的环境加载到内存当中,环境还未启动,那 java 的其他任何东西就更不可能存在,所以它一定是操作系统的语言(比如 C 语言)来实现,所以那些最基础的类也都是由 启动类加载器 来加载的所以BootstrapClassLoader 在 java 中打印出来的就是 null。

三、举例演示

1.在 D:\Test 目录下创建一个文件夹 Test.java,内容如下:

public class Test {
    public static void main(String[] args) {

        System.out.println("====== GrandFather ======");
    }
}

2.在 D:\Test 文件夹下启动命令窗口:

3.命令行输入:javac *.java 回车,此目录下会多出一个 .class 文件

4.把 .class 文件剪切到:C:\Program Files\Java\jre1.8.0_162\classes 目录下(看自己的 jre 在哪里,classes 是自己新建的)

5.将 Test.java 内容修改,并按照 2、3步骤编译出 .class 文件

public class Test {
    public static void main(String[] args) {

        System.out.println("====== Father ======");
    }
}

6.这次将.class 文件放到 C:\Program Files\Java\jre1.8.0_162\lib\ext\classes 下(classes 文件也是自己新建的)

7.回过头来,再将 Test.java 文件内容修改并编译

public class Test {
    public static void main(String[] args) {

        System.out.println("====== MySelf ======");
    }
}

8.此时在命令窗口执行这个 Test.java 文件

9.将 C:\Program Files\Java\jre1.8.0_162\classes 目录下的 .class 文件删除后再执行 Test.java

10.将  C:\Program Files\Java\jre1.8.0_162\lib\ext\classes 下的 .class 文件删除后再执行 Test.java

11.删除  D:\Test 目录下的.class 文件再执行

四、双亲委派机制的作用

  • 防止重复加载同一个.class 保证数据安全;
  • 保证核心.class不能被篡改,保证Class执行安全。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值