【JVM】已验鼎真,鉴定为:妈妈加载的(双亲委派模型)

【JVM】已验鼎真,鉴定为:妈妈加载的(双亲委派模型)

在Java的世界中,类加载器(ClassLoader)是Java虚拟机(JVM)用来动态加载类的基础组件。双亲委派模型(Parent Delegation Model)是Java类加载机制中一个至关重要的设计,它确保Java类加载过程的安全性和稳定性。本文将简单介绍JVM中的类加载器机制及其双亲委派模型。

首先我们来看看类加载器。

一、类加载器概述

Java中的类加载器主要有以下几种:

  1. Bootstrap ClassLoader(引导类加载器)
    • 由C++实现,是JVM自身的一部分。
    • 负责加载Java的核心类库,例如rt.jar中的类。
  2. Extension ClassLoader(扩展类加载器)
    • sun.misc.Launcher$ExtClassLoader实现。
    • 负责加载Java扩展库(JDK扩展目录lib/ext中的JAR包)。
  3. 应用程序类加载器(Application Class Loader)
    • sun.misc.Launcher$AppClassLoader实现。
    • 负责加载应用程序的类路径(classpath)上的类。
  4. User-defined ClassLoader(用户自定义类加载器)
    • 通过继承java.lang.ClassLoader可以实现自定义类加载器。
    • 用于加载特定需求的类,例如网络类加载器、数据库类加载器等。

image-20240605215628999

二、双亲委派模型

双亲委派模型,准确来说,即当一个类加载器收到一个类的加载请求时,首先不会自己尝试去加载它,而是把这一请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求都最终会被传送到顶层的启动类加载器中。

只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。

  1. 检查缓存:类加载器首先检查自己是否已经加载过该类,如果加载过则直接返回。
  2. 委派父类加载器:如果自己没有加载过,则将加载请求委派给父类加载器。
  3. 递归委派:父类加载器同样遵循上述步骤,递归检查其父类加载器,直到顶层的Bootstrap ClassLoader(启动类加载器)。
  4. 加载类:如果顶层的类加载器无法加载该类,则依次往下返回,由各级子类加载器尝试加载该类。
  5. 缓存加载结果:成功加载类后,将该类缓存以便下次直接使用。

双亲委派模型的优点

  1. 安全性:通过双亲委派机制,可以防止核心类库被篡改。例如,Java核心类库中的java.lang.String类只有由Bootstrap ClassLoader加载,防止应用程序自定义一个java.lang.String类来替换。
  2. 避免重复加载:确保同一个类只被加载一次。即使在不同的类加载器中,只要遵循双亲委派机制,类加载器会避免重复加载同一个类。
  3. 模块化:使得类加载器可以在一个隔离的环境中加载类,适应不同的需求,例如应用服务器中不同应用的隔离运行。

双亲委派模型的缺点

  1. 灵活性不足:在某些情况下,双亲委派模型的严格父子关系限制了类加载器的灵活性。例如,开发人员可能希望在应用程序中加载一个与系统类库版本不同的库。
  2. 调试困难:由于类加载过程涉及多个类加载器的协同工作,调试类加载问题时可能比较复杂,尤其是在遇到类加载冲突或类版本不一致的情况。

三、如何打破双亲委派模型

正常加载类的顺序,是用户自定义类加载器 -> 应用程序类加载器 -> 扩展类加载器 -> 引导类加载器,如果不遵循这个顺序,就是在打破双亲委派机制。

而双亲委派过程都是在loadClass方法中实现的,如果想要破坏这种机制,那么就自定义一个类加载器,重写其中的loadClass方法,使其不进行双亲委派即可。

例如:

public class CustomClassLoader extends ClassLoader {
    
    public CustomClassLoader(ClassLoader parent) {
        super(parent);
    }
    
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 不委派给父类加载器,直接尝试加载目标类
        try {
            // 尝试从当前类加载器的资源路径加载类
            byte[] classData = loadClassData(name);
            if (classData != null) {
                return defineClass(name, classData, 0, classData.length);
            }
        } catch (Exception e) {
            // 忽略加载异常
        }
        
        // 如果当前类加载器无法加载,委派给父类加载器
        return super.loadClass(name);
    }
    
    private byte[] loadClassData(String name) {
        // 从文件或其他资源中读取类字节码的逻辑
        // ...
        return null; // 实际实现时应返回有效的字节码数据
    }
}

四、双亲委派模型的示例

以Tomcat为例,Apache Tomcat是一个广泛使用的Java Web服务器,一个web容器可能需要部署多个应用程序,不同的应用程序可能会依赖同一个第三方库的不同版本,但是不同版本的库中某一个类的全路径名可能是一样的。

它提供了一种机制来打破双亲委派模型,以支持不同Web应用之间的类隔离。Tomcat中,每个Web应用都有自己的类加载器,并且Tomcat的类加载机制允许在特定情况下打破双亲委派模型。

Tomcat的类加载器架构如下:

  1. Bootstrap ClassLoader:加载Java核心类库。
  2. System ClassLoader:加载Tomcat自身的类库。
  3. Common ClassLoader:加载Tomcat的共享类库。
  4. Webapp ClassLoader:每个Web应用有独立的类加载器,用于加载该应用的类和库。

如果采用默认的双亲委派类加载机制,无法加载多个相同的类。

所以,Tomcat破坏双亲委派原则,提供隔离的机制,为每个web容器单独提供一个WebAppClassLoader加载器,每个应用都有自己的类加载器WebAppClassLoader,该加载器重写了loadClass方法,会优先加载当前应用下的类,加载不到时再交给WebAppClassLoader的父加载器SharedClassLoader去加载。

打破双亲委派模型是一种特殊的需求,通常用于解决特定的类加载冲突或版本兼容问题。在Tomcat等应用服务器中,通过自定义类加载器和配置,可以实现对类加载过程的精细控制。理解和灵活应用类加载机制,可以帮助开发人员更好地管理和优化Java应用程序的运行环境。

结语

双亲委派机制属于类加载机制的后续,本来应该很早就发出来力,因为内容不多,但是因为笔者很懒所以拖到现在啦~属于是终于填坑了属于是。

参考文献

深入浅出Java类加载机制(双亲委派模型)与自定义类加载器实践_java类的装载机制-CSDN博客

java—双亲委派模型_java中双亲委派模型-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/682189.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

grpc接口调用

grpc接口调用 准备依赖包clientserver 参考博客&#xff1a; Grpc项目集成到java方式调用实践 gRpc入门和springboot整合 java 中使用grpc java调用grpc服务 准备 因为需要生成代码&#xff0c;所以必备插件 安装后重启 依赖包 <?xml version"1.0" encoding&…

云服务(ECS)Docker安装vulhub安装详解

本文以xshell进行远程控制 1.以ssh连接云服务器 ssh 服务器名公网ip [D:\~]$ ssh root47.99.138.9 在弹框中输入密码 2.安装docker curl -s http://get.docker.com/ | sh rootiZbp1fm14idjlfp53akni8Z:~# curl -s https://get.docker.com/ | sh # Executing docker insta…

fairseq框架使用记录

sh命令 cmd"fairseq-train data-bin/$data_dir--save-dir $save_dir--distributed-world-size $gpu_num -s $src_lang -t $tgt_lang--arch $arch--dropout $dropout--criterion $criterion --label-smoothing 0.1--task mmt_vqa--optimizer adam --adam-betas (0.9, 0.98…

Vue的APP实现下载文件功能,并将文件保存到手机中

Vue的APP实现下载文件功能&#xff0c;并将文件保存到手机中 文字说明后台核心代码前台核心代码运行截图项目链接 文字说明 本文介绍Vue实现的APP&#xff0c;将文件下载并保存到手机中&#xff0c;为系统提供导出功能&#xff1b;同时支持导入&#xff0c;即选择本地的文件后&…

【动手学深度学习】卷积神经网络CNN的研究详情

目录 &#x1f30a;1. 研究目的 &#x1f30a;2. 研究准备 &#x1f30a;3. 研究内容 &#x1f30d;3.1 卷积神经网络 &#x1f30d;3.2 练习 &#x1f30a;4. 研究体会 &#x1f30a;1. 研究目的 特征提取和模式识别&#xff1a;CNN 在计算机视觉领域被广泛用于提取图像…

【AI大模型】Transformers大模型库(四):AutoTokenizer

目录​​​​​​​ 一、引言 二、自动分词器&#xff08;AutoTokenizer&#xff09; 2.1 概述 2.2 主要特点 2.3 代码示例 三、总结 一、引言 这里的Transformers指的是huggingface开发的大模型库&#xff0c;为huggingface上数以万计的预训练大模型提供预测、训练等服…

Java基础27,28(多线程,ThreadMethod ,线程安全问题,线程状态,线程池)

目录 一、多线程 1. 概述 2. 进程与线程 2.1 程序 2.2 进程 2.3 线程 2.4 进程与线程的区别 3. 线程基本概念 4.并发与并行 5. 线程的创建方式 方式一&#xff1a;继承Thread类 方式二&#xff1a;实现Runable接口 方式三&#xff1a;实现Callable接口 方式四&…

【操作系统】(详细理解进程的状态)执行状态、就绪状态、阻塞状态、挂起状态

下面是进程的几种状态的概念&#xff1a; 执行状态&#xff1a;当一个进程已获得必要资源&#xff0c;并占有CPU进行执行。 就绪状体&#xff1a;进程已分配到除CPU外的所有必要资源&#xff0c;只要获取CPU允许就可立即执行。 阻塞状态&#xff1a;正在执行的进程&#xff0c;…

C++之虚函数与多态

1、多态 前面三种称为静态绑定&#xff08;静态多态&#xff09;&#xff0c;最后面的虚函数&#xff0c;则称为动态绑定&#xff08;动态多态&#xff09;。 2、静态绑定与动态绑定 要实现动态绑定&#xff0c;就必须使用虚函数。 3、虚函数 只有当你在&#xff1a;基类的指…

计算机组成原理·考点知识点整理

根据往年考试题&#xff0c;对考点和知识点的一个整理。 校验编码 码距 一种编码的最小码距&#xff0c;其实就是指这种编码的码距。码距有两种定义&#xff1a; 码距所描述的对象含义 2 2 2 个特定的码其二进制表示中不同位的个数一种编码这种编码中任意 2 2 2 个合法编码的…

统一响应,自定义校验器,自定义异常,统一异常处理器

文章目录 1.基本准备&#xff08;构建一个SpringBoot模块&#xff09;1.在A_universal_solution模块下创建新的子模块unified-processing2.pom.xml引入基本依赖3.编写springboot启动类4.启动测试 2.统一响应处理1.首先定义一个响应枚举类 RespBeanEnum.java 每个枚举对象都有co…

JVMの垃圾回收

在上一篇中&#xff0c;介绍了JVM组件中的运行时数据区域&#xff0c;这一篇主要介绍垃圾回收器 JVM架构图&#xff1a; 1、垃圾回收概述 在第一篇中介绍JVM特点时&#xff0c;有提到过内存管理&#xff0c;即Java语言相对于C&#xff0c;C进行的优化&#xff0c;可以在适当的…

技术回眸一笑

回忆一下一年前的出差日记吧&#xff0c;那个时候真的是一点经验没有&#xff0c;干硬件又干软件&#xff0c;只能一步一步慢慢摸索&#xff0c;努力过后慢慢成长起来的吧。那个时候甚至开学了都没有正常报道&#xff0c;但是也收获了不少东西&#xff0c;并且也将作为我后来继…

Vue——组件数据传递与props校验

文章目录 前言组件数据传递的几种类型简单字符串类型数据专递其他类型数据(数字、数组、对象)传递注意事项 数据传递值校验限定数据类型 type给定默认值 default指定必选项 required 前言 组件与组件之间并不是完全独立的&#xff0c;他们之间可以进行一些数据的传递操作。传递…

10个高清视频素材库分享,高清高质量的分享给你

今天&#xff0c;我将为各位介绍几个极具价值的高清视频素材库。无论您是短视频创作者、自媒体运营者还是影视后期制作专家&#xff0c;这些素材库将大大提升您作品的质量。现在&#xff0c;让我们直接深入主题&#xff0c;探索这些优秀的资源平台&#xff01; 蛙学府视频素材…

使用cesiumLab使shp转为3dtlies

过程不做赘述&#xff0c;网上大把&#xff0c;说下注意事项。 1. 存储3DTiles 选项 若是打开则输出的文件为glb格式文件,因为glb文件好储存易传输跨平台。cesium可以使用但无法处理&#xff0c;例如改变颜色&#xff0c;改着色器等。若是不打开则输出的文件为bm3d格式文件,此…

ShowDoc item_id 未授权SQL注入漏洞复现

0x01 产品简介 ShowDoc 是一个开源的在线文档协作平台,它支持Markdown、图片等多种格式,方便团队成员共同编辑和分享文档。企业常见使用场景是使用其进行接口文档、内部知识库管理。 0x02 漏洞概述 2024年6月,ShowDoc官方发布新版本修复了一个SQL注入漏洞。鉴于该漏洞无前…

k8s怎么监听自定义资源的变更?(2)

接上一篇当生成下面代码之后怎么去使用呢&#xff1f; 1.生成crd文件 这里我们通过kubebuilder的一个子项目 controller-gen 来生成crd文件 https://github.com/kubernetes-sigs/controller-tools curl -L -o https://github.com/kubernetes-sigs/controller-tools; go ins…

【前端】响应式布局笔记——flex

二、Flex Flex(FlexiableBox:弹性盒子&#xff0c;用于弹性布局&#xff0c;配合rem处理尺寸的适配问题)。 1、flex-direction:子元素在父元素盒子中的排列方式。 父级元素添加&#xff1a;flex-direction: row; 父级元素添加&#xff1a;flex-direction: row-reverse; 父…

基于百度接口的实时流式语音识别系统

目录 基于百度接口的实时流式语音识别系统 1. 简介 2. 需求分析 3. 系统架构 4. 模块设计 4.1 音频输入模块 4.2 WebSocket通信模块 4.3 音频处理模块 4.4 结果处理模块 5. 接口设计 5.1 WebSocket接口 5.2 音频输入接口 6. 流程图 程序说明文档 1. 安装依赖 2.…