Java-51 深入浅出 Tomcat 手写 Tomcat 类加载机制 双亲委派机制 生命周期 插件化

点一下关注吧!!!非常感谢!!持续更新!!!

🚀 AI篇持续更新中!(长期更新)

目前2025年06月13日更新到:
AI炼丹日志-28 - Audiblez 将你的电子书epub转换为音频mp3 做有声书,持续打造实用AI工具指南!📐🤖

💻 Java篇正式开启!(300篇)

目前2025年06月11日更新到:
Java-44 深入浅出 Nginx - 底层进程机制 Master Worker 机制原理 常用指令
MyBatis 已完结,Spring 已完结,深入浅出助你打牢基础!

📊 大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!
目前2025年06月13日更新到:
大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解

请添加图片描述

JVM类加载机制

JVM 的类加载机制(Class Loading Mechanism)是 Java 虚拟机中一个非常核心的部分,它决定了类从哪里来、怎么加载、什么时候初始化等一系列行为。下面我会从 整体流程、类加载器模型、双亲委派机制、类生命周期 等几个方面详细描述。

类加载整体流程

Java 类的加载过程可以分为 五个阶段(有些资料是六阶段,把“使用”也列进去):

  • 加载(Loading)
  • 验证(Verification)
  • 准备(Preparation)
  • 解析(Resolution)
  • 初始化(Initialization)

加载(Loading)

  • 把 .class 文件读入内存,生成一个 java.lang.Class 对象。
  • 由类加载器完成,可能来自本地磁盘、网络、甚至是动态生成的字节码。
  • 指定类的二进制数据的获取方式,不等同于实例化对象。

验证(Verification)

  • 确保字节码符合 JVM 规范,保证运行时安全。
  • 检查格式是否正确、语义是否符合规定、权限是否合法等。

准备(Preparation)

  • 为类的静态变量分配内存,并设置初始默认值(不是显式赋值)。

解析(Resolution)

  • 把常量池中的符号引用转换为直接引用。
  • 如:类名、字段名、方法签名 -> 实际地址。

初始化(Initialization)

  • 正式执行 () 方法(类构造器),也就是执行静态变量的初始化和静态代码块。
  • 这是类加载过程的最后一步,之后类才可以使用。

类加载器模型(ClassLoader)

JVM 中的类加载器负责把类加载进 JVM,并维持一个“类名-类实例”的映射表。

  • Bootstrap ClassLoader(启动类加载器):JVM 内置,用 C++ 实现,JAVA_HOME/lib 核心类,如 java.lang.*
  • Extension ClassLoader(扩展类加载器):加载扩展库,JAVA_HOME/lib/ext
  • App ClassLoader(应用类加载器):最常用,默认加载你的代码,classpath 路径下的类
  • 自定义 ClassLoader:开发者自定义实现,如热部署、解密等

JVM的类机制中有一个非常重要的角色叫做类加载器(ClassLoader),类加载器有自己的体系,JVM内置了几种类加载器,包括:
● 引导类加载器
● 扩展类加载器
● 系统类加载器

双亲委派机制(Parent Delegation Model)

  • 类加载器在加载类之前,会先把请求交给父类加载器,一直向上委托,直到 Bootstrap。
  • 只有当父类加载器无法加载,子加载器才会尝试加载。

这样做的原因是:

  • 防止核心类被“篡改”或“重复加载”,保证安全性和一致性。
  • 如:你不能加载一个伪造的 java.lang.String 类。

比如会进行这样的加载:

AppClassLoader -> ExtClassLoader -> BootstrapClassLoader

类的生命周期(包含类加载阶段)

被主动使用时才会触发类加载(尤其是初始化)

  • new 实例
  • 访问静态变量
  • 调用静态方法
  • 反射调用
  • 子类初始化

类卸载

  • JVM 不再使用某个类,并且加载它的 ClassLoader 被回收,才可能卸载该类(主要出现在 OSGi、Tomcat 这类容器中)。

类加载机制与热部署/插件化的关系

  • 热部署(如 Spring Boot DevTools)通常通过自定义 ClassLoader 隔离加载上下文。
  • 插件系统(如 IDEA 插件)也依赖于 ClassLoader 的命名空间隔离性。

常见场景

  • Tomcat热部署:每次发布使用新的 ClassLoader
  • SPI机制:基于 Thread.currentThread().getContextClassLoader()
  • 解密加载:重写 findClass 方法
  • 沙箱隔离:不同插件使用不同的 ClassLoader
  • AOP/热更新:动态修改或替换 Class 对象

图示内容

它们之间形成父子关系,通过Parent属性来定义这种关系,最终可以形成树形结构。

在这里插入图片描述

● 引导启动类加载器 BootstrapClassLoader:C++编写,加载Java核心库 java.,比如 rt.jar中的类,构造 ExtClassLoader 和 AppClassLoader
● 扩展类加载器 ExtClassLoader:Java编写,加载扩展库 JAVA_HOME/lib/ext 目录下的 jar 中的类,如 classpath 中的 jre,javax.
或者 java.ext.dir 指定位置中的类
● 系统类加载器 SystemClassLoader/AppClassLoader:默认的加载器,搜索环境变量classpath中指明的路径

在这里插入图片描述

另外:用户可以自定义类加载器(Java编写,用户自定义的加载器,可加载指定路径的 class 文件)
当JVM运行过程中,用户自定义了类加载器去加载某些类时,会按照下面的步骤(父类委托机制):
● 用户自己的类加载器,把加载请求传给父加载器,父加载器再传给其父加载器,一直到加载器树的顶层
● 最顶层的类加载器首先针对其特定的位置加载,如果加载不到就转交给子类
● 如果一直到底层的类加载都没有加载到,那么会抛出异常:ClassNotFoundException

因此,按照这个过程可以想到,如果同样在 classpath 指定的目录中和自己工作目录中存放相同的class,会优先加载 classpath 目录中的文件。

双亲委派机制

基本介绍

当某个类加载器需要加载某个.class文件时,它首先把这个任务托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。

机制作用

● 防止重复加载同一个 .class,通过委托机制向上面去问问,加载过了就不加载了,保证数据安全。
● 保证 .class 不能被篡改,通过委托方式,不会去篡改核心 .class,即使篡改也不会加载。即使加载了也不会同一个 .class 对象了。不同的加载器加载同一个.class也不是同一个.class对象。这样保证了class执行安全(如果子类加载器先加载,那么我们写一些与Java.lang包中基础类同名的类,然后再定义一个子类,这样整个应用使用的基础类就变成了我们自定义的类了)
Object类->自定义加载器(可能真正的Object类已经被修改了)

Tomcat的类加载机制

Tomcat 的类加载机制相对于 JVM的类加载机制做了一些改变,没有严格的遵从双亲委派机制,也可以说打破了双亲委派机制。
比如 Tomcat 下,webapps下部署了两个应用:
● app1/lib/a-1.0.jar com.wzk.Abc
● app2/lib/a-2.0jar com.wzk.Abc
不同版本的 Abc 类的内容是不同的,代码是不一样的

在这里插入图片描述

● 引导类加载器 和 扩展类加载器 的作用不变
● 系统类加载器正常情况下加载的是 CLASSPATH 下的类,但是 Tomcat 的启动脚本并未使用该变量,而是加载Tomcat启动的类,比如 Bootstrap.jar,通常在 catalina.bat 或者 catalina.sh 中指定,位于 CATALINA_HOME/bin 下。
● Common 通用类的加载器加载 Tomcat 使用以及应用通用的一些类,位于 CATALINA_HOME/lib下,比如 servlet-api.jar
● Catalina ClassLoader 用于加载器内部可见类,这样类应用程序不能访问
● Shared ClassLoader 用于加载应用程序共享类,这些类服务器不会依赖
● Webapp ClassLoader 每个应用程序都会有一个独一无二的 Webapp ClassLoader,他用来加载本应用程序的 /WEB-INF/classes 和 /WEB-INF/lib 下的类。

Tomcat 8.5

Tomcat 8.5 默认改变了严格的双亲委派机制:
● 首先从 Bootstrap ClassLoader 加载指定的类
● 如果未加载到,则从 /WEB-INF/classes 加载
● 如果未加载到,则从 /WEB-INF/*.jar 加载
● 如果未加载到,则依次从 System、Common、Shared 加载(在这最后一步,遵从双亲委派机制)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从C++编程入手设计模式——责任链模式

从C编程入手设计模式——责任链模式 ​ 当我们的一个请求需要多个对象去处理,但具体由谁来处理,是根据情况动态决定的。例如,一个日志系统中,可能希望把错误信息写入文件,把提示信息输出到控制台,而不是每…

泛型方法调用需要显示指定泛型类型的场景

泛型类型的推断确定 一般来说&#xff0c;泛型类型的推断可以由以下几个场景确定&#xff1a; 变量定义指定类型 List<String> strList new ArrayList<>();ArrayList的泛型类型是依据变量的类型确定的。 方法返回值确定 Overridepublic Function<List<I…

Deep Research:开启深度研究的智能新时代

在当今信息爆炸的时代&#xff0c;人们面临着海量的信息&#xff0c;无论是专业人士还是普通消费者&#xff0c;都迫切需要一种高效、精准的方式来获取和分析信息。OpenAI 推出的 Deep Research&#xff0c;宛如一颗璀璨的新星&#xff0c;在知识的海洋中为我们导航&#xff0c…

曼昆《经济学原理》第九版 宏观经济学 第二十四章失业与自然失业率

以下是曼昆《经济学原理》第九版宏观经济学第二十四章**“失业与自然失业率”**的详细讲解&#xff0c;从零基础开始构建知识框架&#xff0c;结合中国实际案例与生活化比喻&#xff0c;帮助小白系统理解核心概念&#xff1a; 一、知识框架&#xff1a;失业的“全景图” 1. 核…

【软考高级系统架构论文】论软件系统架构风格

论文真题 请以“软件系统架构风格”为论题,依次从以下三个方面进行论述: 1、概要叙述你参与分析和开发的软件系统开发项目以及你所担任的主要工作。 2、分析软件系统开发中常用的软件系统架构风格有哪些?详细阐述每种风格的具体含义。 3、详细说明在你所参与的软件系统开发项…

LeetCode--35.搜索插入位置

解题思路&#xff1a; 1.获取信息&#xff1a; 给定一个升序排列的数组和一个整数&#xff0c;要求查找该整数应该在数组中插入的位置 限制条件是&#xff0c;要求时间复杂度为O(log N) 2.分析题目&#xff1a; 时间复杂度要求O(log N)&#xff0c;那么就使用二分查找法&#x…

Unix、Linux、POSIX、Minix 区别与联系

一、Unix&#xff1a;现代操作系统的技术原型 诞生&#xff1a;1969年贝尔实验室&#xff0c;用C语言重写后实现跨平台&#xff08;1973年&#xff09;。核心设计&#xff1a; 一切皆文件&#xff08;设备/进程均抽象为文件&#xff09;。管道&#xff08;|&#xff09;和文本…

python计算长方形的周长 2025年3月青少年电子学会等级考试 中小学生python编程等级考试一级真题答案解析

python计算长方形的周长 2025年3月 python编程等级考试一级编程题 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】 1、Python比赛 信息素养大赛Python编程挑战赛 蓝桥杯python选拔赛真题详解 蓝桥杯python省赛真题详解 蓝桥杯python国赛真题详解 2、Python考级 p…

使用 RedisVL 进行复杂查询

一、前置条件 在开始之前&#xff0c;请确保&#xff1a; 已安装 redisvl 并激活相应的 Python 环境。运行 Redis 实例&#xff0c;且 RediSearch 版本 > 2.4。 二、初始化与数据加载 我们将使用一个包含用户信息的数据集&#xff0c;字段包括 user、age、job、credit_s…

「Linux文件及目录管理」vi、vim编辑器

知识点解析 vi/vim编辑器简介 vi:Linux默认的文本编辑器,基于命令行操作,功能强大。vim:vi的增强版,支持语法高亮、多窗口编辑、插件扩展等功能。vi/vim基本模式 命令模式:默认模式,用于移动光标、复制、粘贴、删除等操作。插入模式:按i进入,用于输入文本。末行模式:…

电容器保护测控装置如何选型?

在电力系统的无功补偿环节&#xff0c;​电容器保护测控装置是保障并联电容器组安全稳定运行的核心设备。其选型需综合考量保护需求、系统环境及扩展功能。以下是关键选型要素分析&#xff1a; ​一、明确核心功能需求​ 电容器保护测控装置&#xff0c;选型时需匹配电容器组实…

最近小峰一直在忙国际化项目,确实有点分身乏术... [特殊字符] 不过! 我正紧锣密鼓准备一系列干货文章/深度解析

本人详解 大家晚上好呀&#xff01;&#x1f319; 最近小峰一直在忙国际化项目&#xff0c;确实有点分身乏术... &#x1f605; 不过&#xff01; 我正紧锣密鼓准备一系列干货文章/深度解析&#xff08;选一个更符合你内容的词&#xff09;&#xff0c;很快就会和大家见面啦&am…

OpenCV CUDA模块设备层-----设备端(GPU)线程块级别的一个内存拷贝工具函数blockCopy()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在同一个线程块&#xff08;thread block内&#xff0c;将 [beg, end) 范围内的数据并行地复制到 out 开始的位置。 它使用了 CUDA 线程协作机制…

https没有证书可以访问吗?外网怎么访问内网?

没有SSL证书的网站无法正常通过HTTPS协议访问‌。HTTPS的实现必须依赖有效的SSL证书完成加密握手&#xff0c;否则浏览器会直接阻断连接或显示严重的安全警告。‌‌ 一、技术实现层面‌ ‌HTTPS协议强制要求证书‌。 HTTPS基于SSL/TLS协议实现加密通信&#xff0c;而SSL证书是…

Python pytesseract【OCR引擎库】 简介

想全面了解DeepSeek的看过来 【包邮】DeepSeek全攻略 人人需要的AI通识课 零基础掌握DeepSeek的实用操作手册指南【限量作者亲笔签名版售完即止】 玩转DeepSeek这本就够了 【自营包邮】DeepSeek实战指南 deepseek从入门到精通实用操作指南现代科技科普读物AI普及知识读物人工智…

ubuntu安装postman教程并中文汉化详细教程

一、下载postman安装包 通过网盘分享的文件:Postman-linux-x64-8.7.0.tar.gz 链接: https://pan.baidu.com/s/10WYeguDJlK85cKJ6ptX01w?pwd=xqkh 提取码: xqkh 二、解压到/opt目录 tar -zxvf Postman-linux-x64-8.7.0.tar.gz如果子用户没有/opt权限,可以给子用户赋予/opt的…

《垒球知识科普》垒球世界纪录·垒球1号位

奥运垒球冠军记录 历届冠军榜 1996亚特兰大奥运会 冠军&#xff1a;美国队 ⚡ 首届奥运垒球赛&#xff0c;美国主场3战全胜夺冠&#xff01; 1996 Atlanta Olympics Champion: USA ⚡ Dominated all 3 games in first Olympic softball event 2000悉尼奥运会 冠军&#…

通信网络编程3.0——JAVA

主要添加了私聊功能 1服务器类定义与成员变量 public class ChatServer {int port 6666;// 定义服务器端口号为 6666ServerSocket ss;// 定义一个 ServerSocket 对象用于监听客户端连接//List<Socket> clientSockets new ArrayList<>();// 定义一个列表用于存储…

RediSearch `FT.CREATE` 完全参数指南 HASH/JSON 双写实战

1、索引与 Schema 速概 索引 (index) —— 倒排、前缀、向量、Geo … 元数据集合Schema —— 索引蓝图&#xff1a;定义字段、类型、权重、排序及存储策略FT.CREATE —— 创建索引命令&#xff0c;分「索引级参数」和「字段级参数」两层 2 、FT.CREATE 语法模板 FT.CREATE &…

QT学习教程(三十七)

系统繁忙时的响应&#xff08;Staying Responsive During Intensive Processing&#xff09; 当我们调用QApplication::exec()时&#xff0c;Qt 就开始了事件循环。启动时&#xff0c;Qt 发出显示和绘制事件&#xff0c;把控件显示出来。然后&#xff0c;事件循环就开始了&…