【JVM】双亲委派机制

双亲委派机制是常见的面试题。今天我们就一起了解一下。

在讲双亲委派机制之前,首先了解一下类加载器。

全文的思维导图:

类加载器

类加载器的分类

  • JVM支持两种类型的类加载器。分别为引导类加载器自定义类加载器

image-20201120104305271

类加载器的介绍

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

  • 这个类加载使用C/C++语言实现的,嵌套在JVM内部
  • 它用来加载Java的核心库(JAVA_HOME / jre / lib / rt.jar、resources.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.LaunchersAppClassLoader实现
  • 派生于ClassLoader类
  • 父类加载器为扩展类加载器
  • 它负责加载环境变量 classpath系统属性java.class.path指定路径下的类库
  • 该类加载是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载的
  • 通过classLoader.getSystemclassLoader( )方法可以获取到该类加载器

类加载器流程

image-20201120111605341

双亲委派机制

什么是双亲委派机制?

在类加载的时候,系统会首先判断当前类是否加载过,已经加载的类会直接返回,否则会尝试加载,加载的时候不会先尝试加载这个类,而是把请求委派给你父类加载器。每一层加载都是这样,因此所有的请求最终都会到达顶层的启动类加载器,只有当父类无法处理,子类才会尝试自己去加载,当父类的加载器为null,会使用启动类加载器 BoostrapClassLoader作为父类加载器。

好处

  1. 双亲委派模型保证了java程序的稳定执行,避免了类的重复加载.
  2. 保证了核心API的不被篡改

怎么理解核心API不被篡改呐?

下面我们举个例子来做演示:

我们自己定义一个java.lang包,在其下面定义一个String类,里面声明了静态代码块

package java.lang;

/**
 * @author yanshuang
 * @date 2022/1/14 1:22 下午
 */
public class String {

    static {
        System.out.println("我是自定义的String类的静态代码块");
    }

}

在一个测试类中加载String类,看看加载的String类是JDK自带的,还是我们自己编写的

package com.yan.java;

/**
 * @author yanshuang
 * @date 2022/1/14 1:23 下午
 */
public class StringTest {

    public static void main(String[] args) {
        String s = new java.lang.String();
    }
}

结果:程序并没有输出我们静态代码块中的内容,可见仍然加载的是 JDK 自带的 String 类

image-20220114132927011

接下来我们再举个例子

在我们自己定义的 String 类中整个 main( ) 方法

package java.lang;

/**
 * @author yanshuang
 * @date 2022/1/14 1:22 下午
 */
public class String {

    static {
        System.out.println("我是自定义的String类的静态代码块");
    }

    //错误: 在类 java.lang.String 中找不到 main 方法
    public static void main(String[] args) {
        System.out.println("hello,String");
    }

}

结果:程序并没有输出我们静态代码块中的内容,可见仍然加载的是 JDK 自带的 String 类

原因:由于双亲委派机制,我们的String类是由引导类加载器加载的(String为什么是引导类加载器加载的上面解释了),而引导类加载器并没有main方法,所有会报错

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千禧618

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值