1.热更新的概念
热更新就是动态下发代码,它可以使开发者在不发布新版本的情况下,修复 BUG 和发布功能。
一般这样的概念我会去整理它的输入什么,输出什么,来快速将抽象具体化。
热更新的输入是:代码的字节码文件
输出是:运行的结果是走新修改的文件逻辑得出来的
2.使用工具
使用的工具是阿里的Arthas和JDK自带的Java VisualVM
3.操作过程
在服务一直运行的状态下,在线修改一下线上代码,来让第二次同样的请求得到不一样的逻辑结果。
下面开始我的热更新初体验:
1.安装和启动Arthas
安装和启动大家可以去看文章底部引用里面的Arthas的用户手册 比我说的简单清晰,还可以在线运行。
提一句,运行Arthas需要启动的服务的pid:
liunx中使用 ps -ef 命令 对应行的第二个参数就是pid,
windows中可以使用jdk自带的虚拟机监控查看,直接win键+R键 然后输入 jvisualvm 回车就会出现下图中的,很好辨别
2. 反编译线上的类文件
Arthas中的jad命令( jad 类路径.类名)可以直接在线反编译出线上运行的代码(可用于查看自己线上运行的代码是不是最新代码)
也可以使用 jad 类路径.类名 > 要保存的路径+文件名
jad - -source -only com.saicmobility.cms.gtw.controller.DemoController > C://a -aworkCodePlace //cms -gtw //DemoController.java
|
通过上面的命令,拿到了线上DemoController.java的源代码,保存在我的电脑的C://a-aworkCodePlace//cms-gtw//DemoController.java里面
3.修改源代码,然后编译成字节码文件
修改代码:
为了保证字节码文件的替换成功,需要使用指定的类加载器去加载验证修改后的源代码文件的字节码。所以需要先找到原运行中的DemoController类的类加载器
使用sc命令(search classLoad)去查询对应类的类加载器 ,sc命令可以拿到类加载器的许多信息,但是只需要他的hash,所以grep了一下
sc -d *DemoController | grep classLoaderHash
|
拿到了类加载器的hash: 18b4aac2 下一步是要把java文件进行编译class文件
这里使用的是 内存编译命令 mc (Memory Compiler)
mc -c 18b4aac2 C://a -aworkCodePlace //cms -gtw //DemoController.java -d C://a -aworkCodePlace //cms -gtw
|
执行完这个命令,界面会返回一个class文件的保存地址,需要复制保存一下
最后一步:替换运行中的字节码文件。
这里使用的是redefine使jvm重新加载类文件,需要注意是,修改的文件是不允许新增加类的field/method,否则这部会报错。只能修改已有方法的逻辑
redefine C://a -aworkCodePlace //cms -gtw //com//saicmobility//cms//gtw//controller//DemoController.class
|
大功告成,来测试一下热更新的效果。
修改前postman的请求结果:
替换后postman的请求结果:
引用:
①Java动态追踪技术探究
②Java 动态调试技术原理及实践
Arthas 用户文档 https://alibaba.github.io/arthas/#arthas