动态修改java类 并实现热部署

导言

最近学习了使用Arthas 这个工具,被其强大功能所折服,不敢私藏,随分享出来给大家一起学习。

Arthas介绍

Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。
Arthas 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

常用功能

  1. 查看这个类是从哪儿来的
  2. 监控jvm状态
  3. 线上死锁处理
  4. 代码热更新

代码热更新

我在学习这个工具的时候正好遇到一个需要线上修复的bug,而且现在的开发版部署会导致很多数据库没变更的问题。随使用代码热更新机制进行了修改。

热更新的流程:

启动arth:

1
2
wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar --target-ip 0.0.0.0

启动之后要输入 注入的java进程,输入对应的编号就行了

1
2
3
4
5
java -jar arthas-boot.jar --target-ip 0.0.0.0
[INFO] arthas-boot version: 3.1.0
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 189 arthas-demo.jar
这里输入1

反编译要修改的类:

1
jad --source-only com.xxx.controller.withdraw.WithdrawApis > /tmp/WithdrawApis.java

反编译之后再启动一个终端,去/tmp路径修改这个类
修改完成后我们需要找到加载这个类的classLoader 用sc这个命令执行后会得到一个地址

1
2
sc -d *WithdrawApis | grep classLoaderHash
5674cd4d

然后我么能使用内存编译工具把刚修改的类,编译一遍。

1
2
mc -c 5674cd4d /tmp/WithdrawApis.java -d /tmp
/tmp/com/xxx/controller/withdraw/WithdrawApis.class

最后使用redefine命令将这个编译好的类从新加载一遍

1
redefine /tmp/com/xxx/controller/withdraw/WithdrawApis.class

至此,热更新就搞定了,从新访问接口就可以查看到效果了。

参考链接:

  1. Arthas 在线学习网站
  2. Java 动态追踪技术探究