热部署与热加载的核心是用新classloader加载同名类以绕过“同一classloader不可重复define类”的限制。jvm禁止重复define,但允许不同classloader加载相同类;热加载侧重单类替换(如hotswap、hotswapagent),热部署面向模块级更新(如devtools双加载器、tomcat reloadable、sonic/dcevm);均需打破双亲委派并满足类卸载条件(实例、classloader、class对象均无引用)才能安全生效。

Java 中热部署与热加载的实现,核心在于绕过“一个类只能被同一个 ClassLoader 加载一次”的限制。JVM 规范不允许重复 define 同一个类,但允许用新 ClassLoader 加载同名类——这正是所有方案的底层突破口。
热加载:单类字节码动态替换
热加载聚焦于运行时替换单个 class 文件,常见于 IDE 的 HotSwap 或轻量级开发工具:
- JVM 自带的 HotSwap 仅支持方法体修改(如改逻辑、加日志),不支持新增字段、修改签名或增删方法,需配合调试器触发;
-
HotSwapAgent(开源)在 JVM TI 基础上扩展 redefineClasses API,支持新增方法、修改方法体、调整注解等,启动时加
-javaagent:/path/to/hotswap-agent.jar即可; - 手动实现需监听 .class 文件变更 → 创建新自定义 ClassLoader → 调用
defineClass加载新字节码 → 通过反射或代理切换实例引用;旧 ClassLoader 若无强引用,后续 GC 可卸载其加载的类。
热部署:应用级模块/上下文级更新
热部署面向整个模块或 Web 应用,强调“不重启服务”下完成代码、配置、资源的整体刷新:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- Spring Boot DevTools 使用双 ClassLoader 结构:base classloader 加载 Spring 等第三方 jar,restart classloader 加载应用代码;文件变更后丢弃 restart classloader 并重建,实现毫秒级上下文重启;
-
Tomcat 通过
Context reloadable="true"开启,检测WEB-INF/classes或WEB-INF/lib变化,销毁旧 WebAppClassLoader、新建并重新初始化 ServletContext; - OSGi / Sonic / JRebel 更进一步:Sonic 结合 DCEVM + Instrumentation,支持多类结构变更(如新增类、改继承关系);JRebel 则深度集成框架生命周期,接管 Bean 创建与 AOP 代理,使 Spring、Hibernate 等变更即时生效。
关键前提:打破双亲委派与类卸载条件
要让热部署/热加载生效,必须主动打破默认的双亲委派模型,并满足类卸载条件:
- 自定义 ClassLoader 需重写
loadClass,跳过 parent 查找,直接调用findClass加载本地字节码; - 旧类能被卸载的前提是:该类所有实例已回收、加载它的 ClassLoader 实例不可达、
Class对象无任何引用;因此实际中需清理线程局部变量、静态缓存、监听器注册等强引用; - 生产环境慎用纯 ClassLoader 方案——易引发内存泄漏(如 ClassLoader 泄露导致 PermGen/Metaspace 溢出),推荐 JRebel 或 Sonic 这类经过充分验证的商用/开源方案。
为什么不能直接重定义类?
因为 JVM 在 defineClass 阶段会校验类唯一性:同一 ClassLoader 实例对同一全限定名只允许成功 define 一次,二次调用抛 LinkageError: attempted duplicate class definition。所以所有可行方案都依赖“换加载器”,而非“重定义”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










