尽管在生产环境热更新代码,并非很好的行为,极可能致使:热更不规范,同事两行泪。html
但不少时候咱们的确但愿能热更新代码,好比:java
线上排查问题,找到修复思路了,但应用重启以后,环境现场就变了,难以复现。怎么验证修复方案?git
又好比:github
本地开发时,发现某个开源组件有bug,但愿修改验证。若是是本身编译开源组件再发布,流程很是的长,还不必定能编译成功。有没有办法快速测试?spring
Arthas是阿里巴巴开源的Java应用诊断利器,深受开发者喜好。api
下面介绍利用Arthas 3.1.0版本的 jad
/mc
/redefine
一条龙来热更新代码。安全
下面经过Arthas在线教程演示热更新代码的过程。bash
在例子里,访问 curl http://localhost/user/0
,会返回500错误:app
{
"timestamp": 1550223186170,
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.IllegalArgumentException",
"message": "id < 1",
"path": "/user/0"
}
复制代码
下面经过热更新代码,修改这个逻辑。curl
反编译UserController
,保存到 /tmp/UserController.java
文件里。
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
复制代码
用文本编辑器修改/tmp/UserController.java
,把抛出异常改成正常返回:
@GetMapping(value={"/user/{id}"})
public User findUserById(@PathVariable Integer id) {
logger.info("id: {}", (Object)id);
if (id != null && id < 1) {
return new User(id, "name" + id);
// throw new IllegalArgumentException("id < 1");
}
return new User(id.intValue(), "name" + id);
}
复制代码
$ sc -d *UserController | grep classLoaderHash
classLoaderHash 1be6f5c3
复制代码
能够发现是spring boot的 LaunchedURLClassLoader@1be6f5c3
加载的。
保存好/tmp/UserController.java
以后,使用mc(Memory Compiler)命令来编译,而且经过-c
参数指定ClassLoader
:
$ mc -c 1be6f5c3 /tmp/UserController.java -d /tmp
Memory compiler output:
/tmp/com/example/demo/arthas/user/UserController.class
Affect(row-cnt:1) cost in 346 ms
复制代码
再使用redefine命令从新加载新编译好的UserController.class
:
$ redefine /tmp/com/example/demo/arthas/user/UserController.class
redefine success, size: 1
复制代码
再次访问 curl http://localhost/user/0
,会正常返回:
{
"id": 0,
"name": "name0"
}
复制代码
Arthas里 jad
/mc
/redefine
一条龙来线上热更新代码,很是强大,但也很危险,须要作好权限管理。
好比,线上应用启动账号是 admin,当用户能够切换到admin,那么
因此:
最后,Arthas提醒您: 诊断千万条,规范第一条,热更不规范,同事两行泪。
欢迎关注横云断岭的专栏,专一Java,Spring Boot,Arthas,Dubbo。