浅析Java双亲委派机制及其作用

双亲委派机制:当某个类加载器准备加载一个.class字节码文件时,它首先将这个加载任务委派给上一级类加载器,上一级加载器再委派到更上一级类加载器,递归这个操作直到最顶级的类加载器。

一、类加载器的类别

在介绍Java的双亲委派机制的时候,不得不提 ClassLoader(类加载器)

我们编译的Java代码是如何在JVM中运行的?首先源程序(.java文件)被Java编译器编译为.class字节码文件,然后 ClassLoader负责将这些class文件加载到JVM中去执行。

浅析Java双亲委派机制及其作用

浅析Java双亲委派机制及其作用

如上图所示:JVM提供了三层类加载器

  1. BootStrapClassLoader(引导类加载器) 引导类加载器:用 C++编写,是Java自带的类加载器,用于加载JDK内部的类;主要负责加载核心的类库,构造 ExtensionClassLoaderAppClassLoader。Bootstrap类加载器用于加载JDK中$JAVA_HOME/jre/lib下面的那些类,比如rt.jar包里面的类。 由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到引导类加载器的引用,所以不允许直接通过引用进行操作。
  2. ExtensionClassLoader(扩展类加载器) 扩展类加载器:主要负责加载 jre/lib/ext 目录下的一些扩展的jar包或-Djava.ext.dirs指定目录下的jar包。主要用于加载JDK扩展包里的类。一般$JAVA_HOME/lib/ext下面的包都是通过这个类加载器加载的 Java编写,加载扩展库,如 classpath中的 jrejavax.*或者 java.ext.dir 指定位置中的类,开发者可以直接使用标准扩展类加载器。
  3. AppClassLoader(系统类加载器) 系统类加载器:负责java -classpath或-Djava.class.path所指定目录下的类与jar包 主要负责加载应用程序的主函数类。用来加载开发人员自己平时写的应用代码的类的,加载存放在classpath路径下的那些应用程序级别的类的。 Java编写,加载程序所在的目录
  4. CustomClassLoader(用户自定义类加载器)  java编写,用户自定义的类加载器,可加载指定路径的 class文件

二、工作原理

  • 如果一个类加载器收到类加载的请求,并不会自己先加载,而是将加载请求委托给父类的加载器进行加载;
  • 如果父类的加载器还存在其父类加载器,则进一步向上委托,递归这个操作,直至到达最高级的引导类加载器;
  • 如果父类加载器可以完成加载请求,则成功返回,如果父类加载器不能完成加载请求,则子加载器才会尝试自己去加载,这就是双亲委派机制;
  • 父类加载器一层层向下分派任务,如果子类加载器能加载则加载此类,如果直到系统类加载器也无法加载,则抛出异常。

浅析Java双亲委派机制及其作用

从上图我们就容易理解,当一个Test.class文件要加载时:

  • 不考虑用户自定义的类加载器,首先会在 AppClassLoader检查是否加载过,如果已经加载过就无需在加载了;如果没有,就会委派到父加载器,然后调用父加载器的loadClass方法
  • 父类加载器同理也会先检查是否加载过,如果没有再向上委派 这个类似递归的过程,直到到达 BootstrapClassLoader之前,都只是检查是否加载过,并不会选择自己加载
  • 直到 BootstrapClassLoader,已经没有父加载器了,这是开始考虑自己是否能加载了,如果自己不能加载,则下沉到子类加载器去加载,直到最底层
  • 如果没有任何类加载器能够加载,则抛出 ClassNotFoundException异常

三、双亲委派机制的作用

  • 防止同一个 .class文件被重复加载。通过委派机制向上问一问,如果已经加载过,就不用再加载一次,保证数据安全
  • 保证核心 .class文件不能被篡改。通过委派机制,即使不小心篡改了核心 .class文件,也不会被执行,保证了系统级别的类的安全性

四、代码浅析

举例1:建立一个java.lang.String类,写上static代码块

浅析Java双亲委派机制及其作用

在另外的程序中加载 String 类,看看加载的 String 类是 JDK 自带的 String 类,还是我们自己编写的 String 类

浅析Java双亲委派机制及其作用

从输出结果可以看到,程序并没有输出静态代码块的内容,自定义String类并没有被加载,所以加载的是JDK内置的String类

这是因为我们自定义的String类本应被 AppClassLoader加载,但 AppClassLoader并不会先自己加载,而是把加载请求委托给父类的加载器去执行,到了 ExtensionClassLoader发现String类不归自己管,于是委托给父类的加载器( BootStrapClassLoader),引导类加载器发现是java.lang包,所以加载的就是JDK内置的String类

举例2:在自定义的String类中写个main()方法

浅析Java双亲委派机制及其作用

由于双亲委派机制加载的是JDK内置的String类,而在引导类加载器中的核心类库API里的String类并没有main()方法

举例3:在java.lang包下自定义一个AbcTest类

浅析Java双亲委派机制及其作用

报错,java.lang包下不允许自定义类

Original: https://www.cnblogs.com/RebeccaYuan/p/16350750.html
Author: 爱吃的小小白
Title: 浅析Java双亲委派机制及其作用

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/589691/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • spring中bean的生命周期

    bean生命周期简易版 生命周期:1、创建对象(实例化) 生命周期:2、依赖注入(为属性赋值) 生命周期:3、初始化(需要通过bean中init-method属性指定初始化方法) …

    Java 2023年6月16日
    073
  • Linux 进程管理

    Linux 进程管理 在 LINUX 中,每个执行的程序都称为一个进程。每一个进程都分配一个 ID 号(pid,进程号)。 每个进程都可能以两种方式存在的。前台与后台,所谓前台进程…

    Java 2023年6月5日
    077
  • css 隐藏元素

    display , visibility 仅会改变元素显示,不会改变元素种类。可以配合 js 使用使元素可以动态的显示隐藏。 可以使用 display 或 visibility 实…

    Java 2023年6月5日
    095
  • 使用ANSI改变终端输出样式

    默认情况下程序输出到终端的字符样式为白字黑背景,样式、字体比较单一。如想改变程序输出到终端字符的样式等可使用ANSI转移码使其输出具有不同样式; ANSI转义序 ANSI转义序列包…

    Java 2023年6月16日
    070
  • Hbase初识

    简介 数据模型 相关数据库 典型应用 优势 劣势 key-value Redis 缓存 快速查询 存储数据缺乏结构化 列族 Cassandra,Hbase 分布式的文件系统,大规模…

    Java 2023年6月8日
    086
  • js简单实现拦截访问指定网页

    最近闲的无事,写个脚本玩玩,实现拦截访问指定网址 要想实现这个功能,就要自定义一个浏览器插件 最简单的浏览器插件有两个文件,分别是 manifest.json和 **.js。首先新…

    Java 2023年6月8日
    098
  • RabbitMQ 相关概念

    Human beings are designed for many things, but loneliness isn’t one of them. 人类能应对许多…

    Java 2023年6月9日
    096
  • Springboot限流工具之CurrentLimiting

    1.工具简介 CurrentLimiting:基于令牌桶算法和漏桶算法实现的纳秒级分布式无锁限流插件,完美嵌入SpringBoot、SpringCloud应用,支持接口限流、方法限…

    Java 2023年5月30日
    086
  • python 使用wordcloud+jieba生成词云图片

    pip install jiebapip install wordcloud(如果安装失败,https://www.lfd.uci.edu/~gohlke/pythonlibs/#…

    Java 2023年6月16日
    073
  • 浏览器地址栏从输入地址到页面展示都发生了什么

    1 URL输入 2 DNS解析 浏览器会首先从缓存中找是否存在域名,如果存在就直接取出对应的ip地址, 其中会请求 第二步,本地系统缓存 如果浏览器缓存没找到,就检查本地操作系统的…

    Java 2023年6月6日
    089
  • 手撕spring核心源码,彻底搞懂spring流程

    引子 十几年前,刚工作不久的程序员还能过着很轻松的日子。记得那时候公司里有些开发和测试的女孩子,经常有问题解决不了的,不管什么领域的问题找到我,我都能帮她们解决。但是那时候我没有主…

    Java 2023年5月30日
    099
  • 简易线程池的实现

    1 线程池 为了避免多线程操作过程种线程频繁申请和释放所带来的性能消耗,可以提前创建多个线程,当有任务到来时从线程池中选择一个线程执行,执行完后继续在线程池中待命。 核心是使用一个…

    Java 2023年5月30日
    0110
  • 草履虫都能看懂的系统环境变量配置

    超详细的环境变量配置教学(Windows10) 很多刚刚入坑计算机的小伙伴可能对环境变量的配置不太熟悉,如果你还在找教程,那么看到这里,你就不用继续找了(嘿嘿~),废话不多说,让我…

    Java 2023年6月5日
    089
  • Java获取个个地区邮编(附源码、抓取的数据)

    因公司需要..个个地区的邮编..一个个去搜显然是很麻烦的很耗时间、体力… (不想偷懒的程序猿,不是好程序猿,23333,开玩笑滴) 技术栈:Java + Jsoup 开…

    Java 2023年5月29日
    078
  • Java面试题整理

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月7日
    080
  • 【Java分享客栈】从线上环境摘取了四个代码优化记录分享给大家

    因为前段时间新项目已经完成目前趋于稳定,所以最近我被分配到了公司的运维组,负责维护另外一个项目,包含处理客户反馈的日常问题,以及对系统缺陷进行优化。 经过了接近两周的维护,除了日常…

    Java 2023年6月9日
    090
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球