《Java 100 天进阶之路》第64篇:类加载器与热部署(2026版)
第64篇类加载器与热部署2026版系列导航《Java 100 天进阶之路》完整目录 |⬅️ 上一篇第63篇GC调优实战 |➡️ 下一篇第65篇OOM与内存泄漏排查️ 本文阅读地图3 分钟速览第61~63篇搞定了JVM内存和GC但类是如何加载进内存的热部署原理是什么Tomcat为什么能不停机更新本文彻底搞懂类加载器模块核心问题一句话回答类加载器层次类加载器分几层三层Bootstrap根、Extension扩展、Application应用JDK 9模块化替代Extension双亲委派模型为什么这样设计父加载器优先避免核心类被篡改防止重复加载打破双亲委派怎么打破为什么打破Tomcat WebappClassLoader优先自己加载实现Web应用隔离自定义类加载器怎么实现继承ClassLoader重写findClass()读取字节码调用defineClass()热部署原理为什么能不停机更新用新ClassLoader重新加载类让旧ClassLoader被GC回收JDK 9模块化双亲委派变了吗引入ClassLoader分层模块路径优先级高于类路径面试最爱问高频考点有哪些见文末 小节一、核心知识点1. 类加载器层次结构类加载器是JVM的重要组成部分负责将.class文件加载到内存中并生成Class对象。Bootstrap ClassLoader启动类加载器C实现 ↑ 父加载器 Extension ClassLoader扩展类加载器→ JDK 9 改为 Platform ClassLoader ↑ 父加载器 Application ClassLoader应用类加载器 ↑ 父加载器 自定义 ClassLoader热部署、加密class类加载器加载路径说明Bootstrap ClassLoaderrt.jar、jre/lib核心类库C实现Java中为nullExtension ClassLoaderjre/lib/ext扩展类库JDK 9改为Platform ClassLoaderApplication ClassLoaderclasspath应用类加载用户代码JDK 9 变化引入模块化系统JPMSExtension ClassLoader改为Platform ClassLoader。双亲委派逻辑基本不变但模块路径优先级高于类路径。2. 双亲委派模型工作流程类加载请求 ↓ ① Application ClassLoader 收到请求 ↓ 委派给父 ② Extension ClassLoader 收到请求 ↓ 委派给父 ③ Bootstrap ClassLoader 收到请求 ↓ 尝试加载 ├─ 能加载 → 返回 └─ 不能加载 → 向下传递 ④ Extension ClassLoader 尝试加载 ├─ 能加载 → 返回 └─ 不能加载 → 向下传递 ⑤ Application ClassLoader 尝试加载 ├─ 能加载 → 返回 └─ 不能加载 → ClassNotFoundException为什么要双亲委派安全避免核心类库被篡改如自定义java.lang.String不会被加载避免重复加载确保类的唯一性隔离性不同类加载器加载的同名类被视为不同类型二、通俗讲解1分钟开心学类加载器就像一个“找书系统”图书馆里有一本《Java核心卷1》核心类库rt.jar。每个人类加载器都想看这本书Bootstrap图书管理员根加载器负责图书馆最核心的藏书rt.jar是最高权限。如果你的请求能直接从他那里拿到书就直接给你。Extension图书管理员扩展加载器负责图书馆的“扩展书架”ext目录。如果核心书库没有他会去找。Application图书管理员应用加载器负责读者自己的书classpath。如果上面两个管理员都找不到他最后去找。双亲委派原则读者想找一本《Java核心卷1》先问Application管理员应用加载器他直接甩给ExtensionExtension再甩给Bootstrap。Bootstrap找到了直接给读者——父加载器优先避免核心书被篡改。打破双亲委派TomcatTomcat想让每个Web应用每个独立的图书馆分馆有自己的书库。如果读者想找书分馆管理员先在自己分馆找优先自己加载再向上问——隔离不同Web应用的类。核心理解默认是“层层上交”Tomcat是“我先自己找找不到再交上去”。热部署就像“临时换书”服务运行中有人修改了书的内容代码更新。旧的读者旧ClassLoader继续看完旧书然后离开。新的读者新ClassLoader进来后系统给他一本全新的修订版重新加载。旧书没人看后图书馆自动收回旧ClassLoader被GC回收。三、源码核心片段3.1 双亲委派核心源码ClassLoader.loadClassprotectedClass?loadClass(Stringname,booleanresolve)throwsClassNotFoundException{// 1. 检查是否已加载Class?cfindLoadedClass(name);if(cnull){try{// 2. 父加载器不为空 → 委派给父if(parent!null){cparent.loadClass(name,false);}else{// 3. 父加载器为空 → Bootstrap加载器cfindBootstrapClassOrNull(name);}}catch(ClassNotFoundExceptione){// 父加载器加载失败自己加载}if(cnull){// 4. 父加载器加载失败 → 自己加载cfindClass(name);}}returnc;}3.2 自定义类加载器实现自定义类加载器实现热部署、加密class加载等高级功能publicclassCustomClassLoaderextendsClassLoader{privateStringclassPath;publicCustomClassLoader(StringclassPath){this.classPathclassPath;}OverrideprotectedClass?findClass(Stringname)throwsClassNotFoundException{try{// 1. 将类名转换为文件路径StringfileNameclassPathFile.separatorname.replace(.,File.separatorChar).class;// 2. 读取字节码文件byte[]classDataloadClassData(fileName);if(classDatanull){thrownewClassNotFoundException(name);}// 3. 调用defineClass定义类returndefineClass(name,classData,0,classData.length);}catch(IOExceptione){thrownewClassNotFoundException(name,e);}}privatebyte[]loadClassData(StringfileName)throwsIOException{try(FileInputStreamfisnewFileInputStream(fileName);ByteArrayOutputStreambaosnewByteArrayOutputStream()){byte[]buffernewbyte[1024];intlen;while((lenfis.read(buffer))!-1){baos.write(buffer,0,len);}returnbaos.toByteArray();}}}3.3 打破双亲委派Tomcat WebappClassLoader// Tomcat WebappClassLoader 的核心逻辑简化publicClass?loadClass(Stringname,booleanresolve)throwsClassNotFoundException{// 1. 禁止加载核心类库if(name.startsWith(javax.servlet.)){returnparent.loadClass(name);}// 2. 先检查自己是否已加载Class?clazzfindLoadedClass(name);if(clazz!null)returnclazz;// 3. 自己先找打破双亲委派try{clazzfindClass(name);if(clazz!null)returnclazz;}catch(ClassNotFoundExceptione){}// 4. 自己找不到 → 委托父加载器returnparent.loadClass(name,resolve);}四、热部署原理与实现4.1 热部署是什么热部署Hot Deployment是指在不重启应用的情况下动态更新类定义实现代码的热替换。核心原理用新的类加载器重新加载类让旧的类加载器被GC回收。4.2 热部署简易实现publicclassHotDeployDemo{privatestaticvolatileCustomClassLoaderclassLoader;privatestaticfinalStringCLASS_PATH/path/to/classes/;publicstaticvoidreload()throwsException{// 1. 创建新的类加载器CustomClassLoadernewLoadernewCustomClassLoader(CLASS_PATH);// 2. 用新加载器加载目标类Class?clazznewLoader.loadClass(com.example.MyService);Objectinstanceclazz.getDeclaredConstructor().newInstance();// 3. 替换全局实例// 旧实例不再被引用旧ClassLoader可被GC回收// 注需保证旧实例没有任何引用链可达instanceHolderinstance;classLoadernewLoader;}}⚠️ 热部署三个关键点旧实例不能被任何地方引用否则旧ClassLoader无法被GC新旧ClassLoader不能混用两个加载器的类不兼容需要通过接口进行调用避免类型转换冲突4.3 Tomcat热部署原理Tomcat的StandardContext每个Web应用拥有独立的WebappClassLoaderTomcat Container ├── Bootstrap ClassLoaderJVM核心 ├── Catalina ClassLoaderTomcat自身 ├── Common ClassLoader共享库 └── WebappClassLoader每个Web应用独立 ├── WEB-INF/classes └── WEB-INF/lib/*.jar热部署触发机制检测WEB-INF/classes或WEB-INF/lib目录变化标记Context为“重新加载”状态停止当前Context销毁旧WebappClassLoader创建新的WebappClassLoader重新加载所有类启动新Context五、避坑要点错误/误区后果正确做法自定义类加载器未重写findClass永远加载不到类重写findClass()读取字节码调用defineClass()自定义类加载器未设置父加载器破坏双亲委派引发类冲突建议设置parent特殊场景才打破热部署后旧实例未置null旧ClassLoader无法GC元空间OOM用WeakHashMap或主动置null释放引用热部署时新旧类混用ClassCastException通过接口隔离或用Object反射调用不同类加载器的类强转ClassCastException通过接口或反射调用不用强转JDK 9模块系统与类加载器混用模块路径优先级高于类路径了解模块系统与类加载器交互六、面试高频考点Q1双亲委派模型是什么为什么要这样设计类加载器收到请求时先委派给父加载器父加载器无法加载时自己才尝试加载。三层加载器Bootstrap → Extension/Platform → Application。设计目的①安全避免核心类被篡改②避免重复加载③隔离性。Q2如何打破双亲委派模型重写loadClass()方法不先调用父加载器。典型场景Tomcat的WebappClassLoader先自己找再委派给父。JDBC驱动加载Thread.currentThread().setContextClassLoader()也打破了双亲委派。Q3Tomcat为什么需要打破双亲委派每个Web应用需要隔离不同应用可能依赖不同版本的同名类。如果按双亲委派顺序所有应用都用同一个类无法实现隔离。Tomcat让WebappClassLoader优先加载自己WEB-INF/classes和WEB-INF/lib中的类。Q4两个类加载器加载的同一个类能互相转换吗不能。即使类名相同不同类加载器加载的类在JVM中被视为不同的类型强转会抛ClassCastException。这是类加载器隔离性的核心体现。Q5热部署的原理是什么用新的类加载器重新加载目标类替换旧的引用。旧类加载器在没有引用后会被GC回收从而实现不停机更新。关键点确保旧实例没有任何引用链可达新旧类不混用通过接口调用。Q6JDK 9模块化对类加载器有什么影响① Extension ClassLoader → Platform ClassLoader② 模块路径--module-path优先级高于类路径-cp③ 打破双亲委派更复杂涉及模块之间的可见性控制。 面试官追问陷阱加分题追问1“同一个ClassLoader加载的两个同名类是同一个类吗” 是同一个类。JVM中类的唯一标识是“类加载器全限定名”的组合。同一个ClassLoader加载两次同名类会先检查是否已加载直接返回已加载的Class对象。追问2“不重写loadClass只重写findClass能打破双亲委派吗” 不能。loadClass()是骨架方法findClass()只是双亲委派失败后的兜底。要打破双亲委派必须重写loadClass()。findClass()是模板方法模式中的扩展点用于自定义类加载逻辑不改变委派顺序。追问3“Spring Boot的JarLauncher用了什么类加载器机制为什么要这样设计” 使用了LaunchedURLClassLoader它是URLClassLoader的子类打破了双亲委派——优先加载BOOT-INF/classes和BOOT-INF/lib中的类再委托父加载器。目的是让Spring Boot应用能够从嵌套的JAR包fat jar中加载类实现了自包含可执行JAR。七、练习题分析题Tomcat为什么每个Web应用需要独立的类加载器如果共用会怎样代码题编写一个自定义类加载器从指定目录加载.class文件并测试能否成功加载。场景题某系统使用热部署功能频繁发布后出现OutOfMemoryError: Metaspace。分析可能原因和解决方案。 你的学习进度当前第64篇 / 共108篇 ·进阶篇JVM调优与故障排查第61~70篇✅ 已完成基础篇44篇 第45~64篇 正在学第64篇⏳ 待学习第65~108篇 完整目录 学习指南 | 订阅本专栏不错过每一篇 下一篇文章预告下一篇《第65篇OOM与内存泄漏排查》内容简介OOM常见类型与根因、内存泄漏排查工具链jmap、jhat、MAT、Arthas、堆Dump分析实战、生产环境排查流程。JVM调优专题持续深入拿下OOM排查《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇建议收藏 关注一起100天拿offer 点击关注我更新后第一时间收到推送

相关新闻

《Java 100 天进阶之路》第65篇:OOM与内存泄漏排查(2026版)

《Java 100 天进阶之路》第65篇:OOM与内存泄漏排查(2026版)

第65篇:OOM与内存泄漏排查(2026精版) 📌 系列导航:《Java 100 天进阶之路》完整目录 | ⬅️ 上一篇:第64篇:类加载器与热部署 | ➡️ 下一篇:第66篇:JIT编译与性能优化 &…

2026/7/31 5:14:39 阅读更多 →
基于西门子PLC的自动装瓶机控制系统设计与实现

基于西门子PLC的自动装瓶机控制系统设计与实现

1. 自动装瓶机控制系统设计概述在饮料、药品、日化等行业的包装生产线上,自动装瓶机是最关键的设备之一。传统人工灌装方式不仅效率低下,还容易造成产品污染和计量误差。我们团队基于西门子S7-1200 PLC开发的这套控制系统,实现了从空瓶输送到…

2026/7/31 5:14:39 阅读更多 →
JMeter压力测试实战:从电商下单场景到性能瓶颈定位

JMeter压力测试实战:从电商下单场景到性能瓶颈定位

1. 项目概述:为什么我们需要一个JMeter压力测试案例?如果你是一名后端开发、测试工程师或者运维,那么“压力测试”这个词对你来说一定不陌生。它就像给系统做一次全面的“体能检查”,在用户量激增、大促活动来临前,提前…

2026/7/31 5:14:39 阅读更多 →

最新新闻

大模型编程入门:从API调用到本地部署实战指南

大模型编程入门:从API调用到本地部署实战指南

1. 为什么每个程序员都该学大模型编程?三年前我刚接触大模型时,花了整整两周才跑通第一个文本生成demo。现在借助成熟的工具链,新手用Colab笔记本15分钟就能实现相似效果——这就是技术迭代的速度。大模型编程正在从研究实验室走向工程实践&a…

2026/7/31 5:51:52 阅读更多 →
UE5 Fluid Flux插件实战:从原理到应用构建高性能动态水体

UE5 Fluid Flux插件实战:从原理到应用构建高性能动态水体

1. 项目概述:为什么是Fluid Flux?在虚幻引擎5(UE5)的世界里,创造令人信服的水体效果一直是环境美术和程序化内容创作的“圣杯”。从早期的简单平面反射,到基于物理的材质,再到如今追求实时交互的…

2026/7/31 5:51:52 阅读更多 →
大模型AI知识库构建与优化实战指南

大模型AI知识库构建与优化实战指南

1. 大模型AI知识库全景解析最近半年,大模型AI知识库突然成为技术圈的热门话题。作为一名从2016年就开始接触NLP的老兵,我亲眼见证了从规则引擎到BERT,再到今天的大模型知识库的技术演进。与早期知识图谱需要人工构建不同,现代AI知…

2026/7/31 5:51:52 阅读更多 →
日系与欧美妆前乳对比:从设计理念到实战选择指南

日系与欧美妆前乳对比:从设计理念到实战选择指南

那天下午,我在化妆台前对着镜子发呆。左边是跟风买的欧美网红妆前乳,右边是朋友从日本带回来的“cosme大赏”冠军产品。同样的皮肤状态,同样的粉底液,但两边的妆效却像开了滤镜和没开滤镜的区别——一边是浮粉卡纹的社死现场&…

2026/7/31 5:51:51 阅读更多 →
三款AI白底图工具实测:高效搞定电商白底主图

三款AI白底图工具实测:高效搞定电商白底主图

商品图片制作过程中,白底图基本是绕不开的一环。无论是电商平台上架,还是制作商品详情页,经常都会需要一张干净、突出商品主体的白底图。以前制作白底图,通常需要手动抠图、调整边缘,再重新处理背景,步骤比…

2026/7/31 5:51:51 阅读更多 →
练习项目跟进es查询(day10)

练习项目跟进es查询(day10)

es查询代码es_data_router.get("/search", summary"职位搜索") async def search_jobs(# ---------- 关键词 ----------keyword: Optional[str] Query(None, description"搜索关键词,如 Java、前端"),# ---------- 筛选 ----------w…

2026/7/31 5:50:51 阅读更多 →

日新闻

物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:00:34 阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:34 阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:00:34 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/31 1:03:03 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/31 4:19:39 阅读更多 →

月新闻