浅谈一下Java的双亲委派模式
作者:索码理 发布时间:2021-11-12 02:48:17
说起双亲委派模型,不得不说一下类加载器。
类加载器是什么?
当我们编译Java类时,JVM会创建与平台和机器无关的字节码。字节码存储在.class
文件中。当我们尝试使用一个类时,类加载器就会把它加载到内存中,然后把字节码文件转成Class对象。通俗的说类加载器就是将.class
文件转成Class对象的。
类加载器分类
启动类加载器(Bootstrap Class Loader):负责加载存放在 <JAVA_HOME>\lib
目录下的类,或者被-Xbootclasspath
参数所指定的路径中存放的类。比如:rt.jar
、java.lang.*
包下的类。
扩展类加载器(Extension Class Loader):负责加载<JAVA_HOME>\lib\ext
目录中,或者被java.ext.dirs
系统变量所指定的路径中所有的类库。
应用程序类加载器(Application Class Loader):负责加载用户类路径上所有的类库。
双亲委派模型工作流程
当类加载器收到加载类的请求时,它首先会把请求委派给父加载器去完成,每一层都如此,直到把请求委派给最顶层的启动类加载器,只有当父加载器无法加载委派过来的类时,子加载器才会加载。
JVM在加载⼀个类时,会调⽤AppClassLoader的loadClass
⽅法来加载这个类,不过在这个⽅法中,会先使⽤ExtClassLoader的loadClass
⽅法来加载类,同样ExtClassLoader的loadClass
⽅法中会先使⽤BootstrapClassLoader来加载类,如果BootstrapClassLoader加载到了就直接成功,如果 BootstrapClassLoader没有加载到,那么ExtClassLoader就会⾃⼰尝试加载该类,如果没有加载到,那么则会由AppClassLoader来加载这个类。
所以,双亲委派指得是,JVM在加载类时,会委派给ExtClassLoader和BootstrapClassLoader进⾏加载,如果没加载到才由⾃⼰进⾏加载。
这里说的双亲并不是说类加载器之间是以继承方式实现的,而是以组合的方式实现的,通过源码可以证实这点:
java.lang.ClassLoader#loadClass
private final ClassLoader parent;
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
同时,通过源码我们也可以看到类加载器的加载流程是跟我们描述的一样的:先检查请求加载的类型是否已经被加载过,若没有则调用父加载器的loadClass()
方法,若父加载器为空则默认使用启动类加载器作为父加载器。假如父类加载器加载失败,抛出ClassNotFoundException
异常的话,才调用自己的findClass()
方法尝试进行加载。
双亲委派模型好处
保证唯一性,避免重复加载:类的加载随着它的类加载器一起具备了层级关系,通过这种层级关系避免了重复加载,父类加载器加载了该类,子加载器就无需加载了。
避免核心类被篡改:核心类由启动类加载器加载,即使用户自定义同名核心类也不会被加载。
来源:https://blog.csdn.net/qq_39654841/article/details/128487337


猜你喜欢
- 先给大家展示下效果图,大家觉效果满意,请参考实现代码。直接上代码:private void setDialog(){View view =
- 问题分析疑惑满满小枫听到这个面试题的时候,心想这是什么水面试官,怎么问这么简单的题目,心想一个for循环加上equal判断再删除不就完事了吗
- 用Dockerfile 构建一个java的编译环境,这里整理下实现步骤:1、包括以下软件包ubuntujdkmavensvn2、jdk、ma
- 这篇文章主要介绍了JAVA基于SnakeYAML实现解析与序列化YAML,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考
- vs2005中总是保留最近打开的项目和文件的记录,甚至是以删除的它也不删,-_-!下面介绍几种删除的方法:第一种:建立一个bat文件,以后双
- seata的部署和集成1.部署Seata的tc-server1)下载首先我们要下载seata-server包,地址在http/seata.i
- android绘制圆形图片的两种方式看下效果先下面有完整的示例代码使用BitmapShader(着色器)我们在绘制view 的时候 就是小学
- 一个发送验证码的需求:包括限制文本框输入长度和只允许输入数字按惯例 先上图:class MyBody extends StatefulWid
- 前言简单来说机器学习的核心步骤在于“获取学习数据;选择机器算法;定型模型;评估模型,预测模型结果”,下面本人就以判断日报内容是否合格为例为大
- 前言今天记录一个前段时间遇到的一个小问题的解决方法, 跨域!!!相信跨域这个问题, 做开发的或多或少都遇到过, 而且已经有很多博主已经分享了
- 简介GraalVM是高性能的JDK,支持Java/Python/JavaScript等语言。它可以让Java变成二进制文件来执行,让程序在任
- 在练习Java的Scanner时,EditPlus如何读取从键盘输入的数呢?例如如下程序,编译通过,运行时却输入不了数据:package m
- JPA like 模糊查询 语法格式public List<InstitutionInfo> getAllInstitution
- 1.加入mybatis-spring-boot-stater的Maven依赖 <dependency>
- 0-1背包的问题背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重
- 相关文章:Java使用POI导出Excel(一):单sheetJava使用POI导出Excel(二):多个sheet相信在大部分的web项目
- C语言数据结构实现银行模拟实现代码:#include <stdio.h> #include <stdlib.h> #
- 多线程一直是工作或面试过程中的高频知识点,今天给大家分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用
- 可以使用System.ServiceProcess.ServiceController这个类允许连接到正在运行或者已停止的服务、对其进行操作
- 报错翻译: compileSdkVersion android-24”需要JDK 1.8或更高版本编译。报错现象如下图:原因:st