62

Arthas实践--jad/mc/redefine线上热更新一条龙

 5 years ago
source link: http://hengyunabc.github.io/arthas-online-hotswap/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

尽管在生产环境热更新代码,并不是很好的行为,很可能导致:热更不规范,同事两行泪。

但很多时候我们的确希望能热更新代码,比如:

线上排查问题,找到修复思路了,但应用重启之后,环境现场就变了,难以复现。怎么验证修复方案?

又比如:

本地开发时,发现某个开源组件有bug,希望修改验证。如果是自己编译开源组件再发布,流程非常的长,还不一定能编译成功。有没有办法快速测试?

Arthas是阿里巴巴开源的Java应用诊断利器,深受开发者喜爱。

下面介绍利用Arthas 3.1.0版本的 jad / mc / redefine 一条龙来热更新代码。

Arthas在线教程

下面通过Arthas在线教程演示热更新代码的过程。

ERBzMfz.png!web

在例子里,访问 curl http://localhost/user/0 ,会返回500错误:

{
    "timestamp": 1550223186170,
    "status": 500,
    "error": "Internal Server Error",
    "exception": "java.lang.IllegalArgumentException",
    "message": "id < 1",
    "path": "/user/0"
}

下面通过热更新代码,修改这个逻辑。

jad反编译代码

反编译 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查找加载UserController的ClassLoader

$ sc -d *UserController | grep classLoaderHash
 classLoaderHash   1be6f5c3

可以发现是spring boot的 LaunchedURLClassLoader@1be6f5c3 加载的。

mc内存编绎代码

保存好 /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热更新代码

再使用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,那么

  • 用户可以修改,获取到应用的任意内存值(不管是否java应用)
  • 用户可以attach jvm
  • attach jvm之后,利用jvm本身的api可以redefine class

所以:

  • 应用的安全主要靠用户权限本身的管理
  • Arthas主要是让jvm redefine更容易了。用户也可以利用其它工具达到同样的效果

最后,Arthas提醒您: 诊断千万条,规范第一条,热更不规范,同事两行泪

Arthas实践系列


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK