热部署 和 热加载

本文主要讲热部署和热加载的区别、原理,以及常用的热部署的方式实践心得,其中包括HotSwap、Spring-loaded、Spring-boot-devtools、HotCode2和JRebel,诸多方式任你选择,希望能为你的开发进一步提效

1 热部署和热加载

开篇先说下热部署和热加载的区别:
热部署:在服务器运行时重新部署应用,也就是说在不停止容器的情况下实现整个应用的重新加载部署,这种方式会释放内存,多用于生成环境
热加载:在应用运行时重新加载class,主要依赖于Java的类加载机制,如果监控的类文件有改变,则重新载入,多用于应用开发阶段,又叫开发者模式,在开发过程中会经常性的进行修改文件或debug,频繁启动应用会花费很多时间成本,热加载机制可以极大的提升开发效率,这也是写这篇文章的主要原因,提高大家的开发效率。
但我们通常所说的热部署其实包括热加载的,可以理解为热加载是热部署的一种VIP情况

2 热加载的原理

2.1 类加载过程

在了解热加载之前,首先说下类加载的过程,类加载的过程简单来说就是JVM虚拟机把.class文件中类信息加载进内存,并进行解析生成对应的class对象的过程;类加载的过程主要分为三大部分:加载、连接、初始化,其中连接又分为:验证、准备、解析;示例图如下:

image.png | left | 747x210

  • 编译:把Java文件编译成.class字节码的过程
  • 加载:类加载过程的开始,把class字节码文件从各个源通过类加载器载入内存中
  • 连接
    • 验证:确保类加载的正确性,保证加载进来的字节流符合JVM规范,不会造成安全问题
    • 准备:类变量(注意,不是实例变量,是static变量)分配内存,并且设置这些类变量的初始值
    • 解析:将常量池内的符号引用替换为直接引用的过程
  • 初始化:是类加载过程的最后一步,可以理解为是执行类构造器<clinit>()方法的过程,真正开始执行类中定义的Java程序代码或者说字节码。

2.2 剖析原理

        首先通过Java编译器把Java文件编译成class字节码,Java类加载器(classLoad)读取字节码到内存中,生成实例对象,一个类加载器中的Java全限定名是全局唯一的,也就是说一个类加载器只能加载一个同名类,classLoader内部会缓存已经加载过的class,重新加载的话,是直接读  取缓存的,如果是使用自定义的classLoader加载,不使用双亲委派模型,绕过判断,但是在JVM解析、验证class时也是会抛出异常的,所以实现__热部署的关键是可更改已加载的class文件,用新的class文件替换同名的old class文件(或者更改class字节码),或者是重新创建一个classLoader进行加载,然后把老的classLoader卸载掉__;第二种方案可以理解成热部署,所以这种方案为开发提效有限;而第一种方案是更新或替换old class文件所以这种热加载的方式对开发提效非常明显。

2.3 发展历程

     在JDK1.4时,Sun在JVM中引入了HotSwap的实验性技术,这一技术被合成到了Debugger API内部,其允许调试者使用同一个类标识来更新类的字节码,这就意味着在不重载容器的情况下,允许动态更新class文件,使应用程序在执行时可执行新的代码。
    从JDK1.5开始,提出了“Instrumentation”特性,可通过Instrumentation API直接提供给Java应用使用,开发者可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义,但在 JDK1.5 中,需要要求在运行前利用命令行参数或者系统参数来设置代理类。
    JDK1.6之后,对Instrumentation进行了加强,启动后的 instrument、本地代码(native code)instrument,以及动态改变 classpath 等等,“java.lang.instrument”包的具体实现,依赖于 JVMTI(Java Virtual Machine Tool Interface),JVMTI 提供了一套”代理”程序机制,可以支持第三方工具程序以代理的方式连接和访问 JVM,并利用 JVMTI 提供的丰富的编程接口,完成很多跟 JVM 相关的功能,JVMTI 还在虚拟机内存管理,线程控制,方法和变量操作等等方面提供了大量有价值的函数,Instrumentation 的最大作用,就是类定义动态改变和操作。--参见IBM Developer

3 Hot Swap实现热部署

这种方式有两个弊端:
  1 就是仅限于修改方法体,对比如新增方法、字段之类 就需要重新部署才可以了,这种方式有没有解决方案呐,答案是肯定的,收费的JRebel,或者免费的HotSwapAgent+DCEVM

2 HotSwap需要依托于IDE集成,比如主流的IDE:IntlliJ IDEA、Eclipse、MyEclipse、NetBeans等

下面HotSwap以IDEA为例实现方法体内的热部署功能

3.1 IDEA基于HotSwap的热部署功能

使用IDEA自动编译部署功能,实现应用的热部署(Hot Swap)

3.1.1 检查是否开启HotSwap,默认是开启的

image.png | left | 527x207

3.1.2 开启IDEA自动编译功能

弹出registry浮层面板,快捷键control+shift+a,然后找到compiler.automake.allow.when.app.runing勾选

image.png | left | 554x439

快捷键不对的可以在keymap面板中找下:

image.png | left | 551x145

3.1.3 设置IDEA自动编译

image.png | left | 655x2

3.1.4 手工编译(注意类加载顺序)

修改某个类中的方法中的内容后,在菜单栏中Build菜单中Recompile或右键点击Recompile,编译完成之后,再次访问,可验证加的内容是否生效

image.png | left | 341x170

或:

image.png | left | 320x121

点击Recompile之后,第一次会弹出框让选择:是否重新加载classes,选择是

image.png | left | 296x109

3.1.5 验证结果

热部署2.png | center | 687x184

4 Spring-loaded实现热部署

  spring-loaded是针对Springboot类的项目,springloaded热部署只可以修改已有方法与页面,如果是新加的方法或者类则无法实现热部署,并且需要配置启动参数-javaagent(-javaagent:.\lib\springloaded-1.2.8.RELEASE.jar -noverify)。这种方式需要指定springloaded jar包的位置,我不怎么用,就不多说,有兴趣的同学可以自己玩下。

<dependency>  
           <groupId>org.springframework</groupId>  
           <artifactId>springloaded</artifactId>
       </dependency>  

5 Spring-boot-devtools实现热部署

注意:PandoraBoot不支持devtools实现热部署
      Devtools是为springboot应用提供的一个开发者服务模块,其原理就是上面第二章节所说的先重新创建类加载器然后销毁old类加载器;devtools在监控到代码有更改之后,会快速重启应用,这里重启并不是整个应用重启,而是重新加载部分classLoader,因为其有两个classLoader,一个classLoader加载不会改变的类(如各种第三方jar包、二方包等),另一个classLoader加载会更改的类可以理解成自己开发的类,被称为RestartClassLoader,这样有代码更新时,会重新创建一个RestartClassLoader,并销毁之前的RestartClassLoader,由于只加载部分类,所以相对整个应用重启 用时相对较少,但相较于JRebel和hotSwap速度还是大打折扣的,比hotSwap优势就是可以支持静态资源文件(页面、配置文件等,监控范围是classpath下的文件)、新增方法、字段之类的更新。

源码:

image.png | left | 693x183

image.png | left | 636x279

5.1 常用配置项

  • 默认情况下,以下文件夹下的文件修改不会使应用重启,但是会重新加载(devtools内嵌了一个LiveReload server,当资源发生改变时,浏览器刷新)。

    META-INF/maven/<strong>,META-INF/resources/</strong>,resources/<strong>,static/</strong>,public/<strong>,templates/</strong>,**/*Test.class,**/*Tests.class,git.properties,META-INF/build-info.properties
    
  • 如果想改变默认的设置,可以自己设置不重启的目录:spring.devtools.restart.exclude=static/**,public/**,这样的话,就只有这两个目录下的文件修改不会导致restart操作了。

  • 如果要在保留默认设置的基础上还要添加其他的排除目录:spring.devtools.restart.additional-exclude

源码:

image.png | left | 747x109

  • 如果想要使得当非classpath下的文件发生变化时应用得以重启,使用:spring.devtools.restart.additional-paths,这样devtools就会将该目录列入了监听范围

源码:

image.png | left | 747x126

  • 如果你想关闭自动restart功能,通过spring.devtools.restart.enabled属性配置即可
  • 如果想开启或关闭远程debug功能,通过spring.devtools.remote.debug.enabled属性配置,默认是true

源码:

image.png | left | 736x134

  • 实现页面热部署,通过spring.thymeleaf.cache属性配置为false即可,默认为true

还有远程相关的其他一些配置、代理配置、重启轮询时间等待时间等的配置可以查看源码中的spring-configuration-metadata.json文件

5.2 使用示例

1 添加依赖

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <scope>runtime</scope>
    </dependency>

<plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <fork>true</fork>
        </configuration>
      </plugin>

Eclipse: 下面是在eclipse中实现热部署的演示,项目启动后,新加类TestController,并新增getName()方法,保存后可以观察到后台已进行热部署了,在浏览器中访问如下RPC,可正常返回结果

image.png | left | 674x405

6 JRebel 实现热部署

强烈推荐,有商业版和个人免费版(个人版申请通道好像已关闭,但有试用版或其他解决方案(仅供学习使用,请支持正版))
它可以在无需动态类加载器的情况下更新类,且只做极少的限制(改变static静态字段值不支持),它的工作原理就是监控磁盘上的已编译的class文件,并通过rebel.xml配置文件把归档的应用(zip、jar、war)和应用模块间建立一个对应关系,通过该文件JRebel可以直接找到归档应用对应的源文件,当某个类被更新时,该文件告诉JRebel在哪里可以找到源文件,使其被从工作区中而不是从归档文件中读取。也就是因为它的这一特性,使其可以对诸如Html、xml、.properties、.yml等资源类的文件也可以及时更新。

6.1 使用示例

6.1.1 安装JRebel

image.png | left | 672x104

6.1.2 使用JRebel启动项目

安装完成之后,会在工作栏中显示出JRebel图标

image.png | left | 393x72


image.png | left | 452x110

6.1.3 验证JRebel是否启动成功

项目启动时,控制台出现如下信息时表示JRebel配置正确可以正常使用

image.png | left | 571x283

6.1.4 设置热部署模块

在IDEA视图窗口中打开JRebel,选中jrcon复选框,JRebel会自动在对应模块下生成rebel.xml文件,该文件将被放置到项目的源代码树中,对于Maven项目,它将被放置到src/main/resources中,以便在构建期间自动获取。

image.png | left | 400x229

注:每个模块下resources资源文件下会产生一个rebel.xml配置文件,文件的功能基本同HotCode2的workspace.xml,用于指定target/classes的dir路径,当文件有更新时JRebel会自动将其映射到工作区。

6.1.5 验证

image.png | left | 545x270

点击保存之后,可以在控制台看到JRebel打印的Reloading日志,说明新加的方法已经生效

image.png | left | 553x144

7 总结

有了热部署不仅能大幅度节省重启项目的时间,而且能够在编程时避免中断思路,将更多的时间用于Coding和思考问题。
本文主要是基于本地开发的维度进行演示说明,具体使用哪一种各位可根据自己开发中实际情况进行自由选择,当然个人还是比较优先推荐JRebel,稳定好用省心,其次是HotCode2,如果原生的SpringBoot类(PandoraBoot不支持)的项目可以使用Spring-boot-devtools或者Spring-loaded尝尝鲜,最后支持工程热部署方式最少的但也是最方便的就是HotSwap,各个IDE工具基本都已集成开启即可使用。

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

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

相关文章

在Linux系统中安装MySQL数据库

目录 一、MySQL简介 二、MySQL安装步骤 1、下载MySQL的YUM仓库文件 2、安装MySQL源 3、解决密钥异常问题 4、安装MySQL服务器 5、开启MySQL服务 6、查看MySQL服务器中root用户的初始密码 7、使用初始密码登录MySQL服务器 8、修改root用户登录MySQL服务器的密码 三、…

使用Java语言判断一个年度是不是闰年

一、 代码说明 引入Scanner函数&#xff0c;将类命名为Judge类&#xff0c;使用try语句和catch语句将整体代码包围起来&#xff0c;使用if语句来判断是否为闰年&#xff0c;输入年份&#xff0c;然后得到相应的结论。 二、代码 import java.util.Scanner; public class Judg…

ElementUI中修改el-table的滚动条样式

注意&#xff1a;本文仅基于webkit引擎浏览器&#xff1b; 如果是火狐浏览器&#xff0c;则是-moz-&#xff1b; 部分webkit引擎浏览器&#xff1a;Google Chrome谷歌浏览器、Safari浏览器、搜狗高速浏览器、QQ浏览器、360极速浏览器等… 当内容超出容器时会出现滚动条&#…

HarmonyOS4.0系统性深入开发01应用模型的构成要素

应用模型的构成要素 应用模型是HarmonyOS为开发者提供的应用程序所需能力的抽象提炼&#xff0c;它提供了应用程序必备的组件和运行机制。有了应用模型&#xff0c;开发者可以基于一套统一的模型进行应用开发&#xff0c;使应用开发更简单、高效。 HarmonyOS应用模型的构成要…

Spring基础-IOC-DI-AOP

第一部分:Spring基础 文章目录 第一部分:Spring基础一、核心概念1.什么是Spring?2.Spring架构3.Spring优势 二、控制反转1.为什么要控制反转?2.组件化方式编程案例(Test01_di)3.采用组件化思维,装配打印机(Test01_di) 三、面向切面编程(AOP)方面编程1.什么是AOP?2.如何实现A…

AI时代Python量化交易实战:ChatGPT引领新时代

文章目录 《AI时代Python量化交易实战&#xff1a;ChatGPT让量化交易插上翅膀》关键点内容简介作者简介购买链接 《AI时代架构师修炼之道&#xff1a;ChatGPT让架构师插上翅膀》关键点内容简介作者简介 赠书活动 《AI时代Python量化交易实战&#xff1a;ChatGPT让量化交易插上翅…

MATLAB - 读取双摆杆上的 IMU 数据

系列文章目录 前言 本示例展示了如何从安装在双摆杆上的两个 IMU 传感器生成惯性测量单元 (IMU) 读数。双摆使用 Simscape Multibody™ 进行建模。有关使用 Simscape Multibody™ 构建简易摆的分步示例&#xff0c;请参阅简易摆建模&#xff08;Simscape Multibody&#xff09…

设计模式(4)--对象行为(2)--命令

1. 意图 将一个请求封装为一个对象&#xff0c;从而使你可用不同的请求对客户进行参数化&#xff1b;对请求排队或记录请 求日志&#xff0c;以及支持可撤销的操作。 2. 四种角色 接收者(Receiver)、抽象命令(Command)、具体命令(Concrete Command)、请求者(Invoker) 3. 优点…

【NI-RIO入门】使用其他文本语言开发CompactRIO

1.FPGA 接口Python API Getting Started — FPGA Interface Python API 19.0.0 documentation 2.FPGA接口C API FPGA 接口 C API 是用于 NI 可重配置 I/O (RIO) 硬件&#xff08;例如 NI CompactRIO、NI Single-Board RIO、NI 以太网 RIO、NI FlexRIO、NI R 系列多功能 RIO 和…

Python生成圣诞节贺卡-代码案例剖析【第18篇—python圣诞节系列】

文章目录 ❄️Python制作圣诞节贺卡&#x1f42c;展示效果&#x1f338;代码&#x1f334;代码剖析 ❄️Python制作圣诞树贺卡&#x1f42c;展示效果&#x1f338;代码&#x1f334;代码剖析&#x1f338;总结 &#x1f385;圣诞节快乐&#xff01; ❄️Python制作圣诞节贺卡 …

【数字通信原理】复习笔记

哈喽&#xff89;hi~ 小伙伴们许久没有更新啦~ 花花经历了漫长的考试周~ 要被累成花干啦。今天来更新《数字通信原理》手写笔记给需要的小伙伴~ &#xff08;注:这是两套笔记&#xff0c;是需要结合来看的哦~&#xff09; 第一套的笔记请结合bilibili:张锦皓的复习课程来哦。 第…

sql_lab之sqli中的报错注入,less13

报错注入&#xff08;less-13&#xff09; 正常报错注入&#xff1a; 1.输入用户名和密码123 123显示登录错误 2.输入用户名和密码123’ 123显示登录错误 123后面有’)说明是’)注入 3.查询数据库名 1) and updatexml(<a><b></b></a>,concat(1111…

二维码智慧门牌管理系统升级:强化用户管理合规性

文章目录 前言一、功能优化和多层级管理二、强大的合规性与权限配置三、提升管理效率与系统安全性 前言 随着科技迅速发展&#xff0c;二维码智慧门牌管理系统已经成为各组织机构首选的入口&#xff0c;提高了信息管理效率并确保了数据安全。然而&#xff0c;用户需求变化和法…

<HarmonyOS第一课>运行Hello World

下载与安装DevEco Studio 在HarmonyOS应用开发学习之前&#xff0c;需要进行一些准备工作&#xff0c;首先需要完成开发工具DevEco Studio的下载与安装以及环境配置。 进入DevEco Studio下载官网&#xff0c;单击“立即下载”进入下载页面。 DevEco Studio提供了Windows版本和…

OC学习笔记--基础篇

本文简要介绍了一些oc的基础类型&#xff0c;包括数组、字典、字符串、消息传递、类、对象、方法、属性、协议和转发&#xff0c;希望对你有帮助。 OC数据类型 打印—类似print NSlog("hello word");数组 NSMutableArray &#xff08;可变数组&#xff09;和 NSAr…

音画欣赏|《同杯万古尘》

《同杯万古尘》 尺寸&#xff1a;69x35cm 陈可之2023年绘 《拟古十二首-其九》 李白 生者为过客&#xff0c;死者为归人。 天地一逆旅&#xff0c;同悲万古尘。 月兔空捣药&#xff0c;扶桑已成薪。 白骨寂无言&#xff0c;青松岂知春。 前后更叹息&#xff0c;浮荣安足珍&am…

【SpringMVC】REST(Representation State Transfer)ful开发

REST全称Representation State Transfer&#xff0c;表现形式状态转换 文章目录 1. 为什么提出了REST&#xff1f;2. RESTful入门案例案例代码修改请求方式修改成RESTful风格&#xff0c;并以POST方式提交 RESTful格式下传参RESTful入门案例总结RequestBody&#xff0c;Reques…

2023 Intellij IDEA的热部署配置

第一步&#xff1a;导入依赖 <!--热部署--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency>第二步&#xff1a;配置idea

【Git 小妙招】学习多人协作场景(万字图文讲解+实战练习)

文章目录 前言1. 多人协作(场景一)2. 多人协作(场景二)3. 解决一个问题总结 前言 还记得我们学习 Git 是为了什么吗? 当然是实现多人协作了. 在学习了解博主前面关于 Git 的文章后, 我们就可以模拟来进行一些超超超简单的多人协作场景了. 本文就简单举两个多人协作的例子. 关…

C++ 强制类型转换static_cast<typeName>

C允许通过强制类型转换机制显式地进行类型转换。强制类型转换的格式有两种。 如&#xff1a; 为将存储在变量nData中的int值转换为long类型&#xff0c;可以使用下面的表达式中的一种&#xff1a; (long)nData …