Arthas热部署

1 思路

  • 1.在出问题的服务器上部署一个 arthas,并启动。
  • 2.jad --source-only 类全限定名 > 目录/文件名.javajad 命令反编译,然后可以用其它编译器,比如 vim来修改源码。
  • 3.修改错误代码。
    1. 查看类加载器的hashcodesc -d 类全名。
  • 5.mc-c类加载器的hashcode目录/文件名.java -d 输出目录mc 命令用来编译修改过的代码。
  • 6.retransform class文件所在目录/xxx.classretransform 命令加载新的字节码。

2 实操

  • 这里用jdk17启动项目和arthas
/opt/jdk17/jdk-17.0.10/bin/java -jar /opt/test-spi.jar
/opt/jdk17/jdk-17.0.10/bin/java -jar arthas-boot.jar 
选择PID
1
[INFO] arthas home: /opt/arthas
[INFO] Try to attach process 9088
Picked up JAVA_TOOL_OPTIONS: 
[INFO] Attach process 9088 success.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.                           
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'                          
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.                          
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |                         
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'                          

wiki       https://arthas.aliyun.com/doc                                        
tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html                  
version    3.7.2                                                                
main_class                                                                      
pid        9088                                                                 
time       2024-04-09 09:38:38   
  • 反编译要修改的类的源码
jad --source-only com.logicfeng.testspi.controller.TestSpiController > /opt/testSpi/TestSpiController.java
  • 因为编译一个类可能需要其他import的类,此时可先查找下这个类的加载器的hash码:sc -d类全名
[arthas@9088]$ sc -d com.logicfeng.testspi.controller.TestSpiController
 class-info        com.logicfeng.testspi.controller.TestSpiController                                                                                                                                                  
 code-source       nested:/opt/test-spi.jar/!BOOT-INF/classes/!/                                                                                                                                                       
 name              com.logicfeng.testspi.controller.TestSpiController                                                                                                                                                  
 isInterface       false                                                                                                                                                                                               
 isAnnotation      false                                                                                                                                                                                               
 isEnum            false                                                                                                                                                                                               
 isAnonymousClass  false                                                                                                                                                                                               
 isArray           false                                                                                                                                                                                               
 isLocalClass      false                                                                                                                                                                                               
 isMemberClass     false                                                                                                                                                                                               
 isPrimitive       false                                                                                                                                                                                               
 isSynthetic       false                                                                                                                                                                                               
 simple-name       TestSpiController                                                                                                                                                                                   
 modifier          public                                                                                                                                                                                              
 annotation        org.springframework.web.bind.annotation.RestController,org.springframework.web.bind.annotation.RequestMapping                                                                                       
 interfaces                                                                                                                                                                                                            
 super-class       +-java.lang.Object                                                                                                                                                                                  
 class-loader      +-org.springframework.boot.loader.launch.LaunchedClassLoader@5305068a                                                                                                                               
                     +-jdk.internal.loader.ClassLoaders$AppClassLoader@46fbb2c1                                                                                                                                        
                       +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@48b070d8                                                                                                                                 
 classLoaderHash   5305068a   
  • 编译修改后的类
[arthas@9088]$ mc -c 5305068a /opt/testSpi/TestSpiController.java -d /opt/testSpi
Memory compiler output:
/opt/testSpi/com/logicfeng/testspi/controller/TestSpiController.class
Affect(row-cnt:1) cost in 1164 ms.
  • 让类加载器重新加载新编译的字节码,加载新编译的.class文件,retransformJVM
[arthas@9088]$ retransform /opt/testSpi/com/logicfeng/testspi/controller/TestSpiController.class
retransform success, size: 1, classes:
com.logicfeng.testspi.controller.TestSpiController
  • jad命令查看
[arthas@9088]$ jad com.logicfeng.testspi.controller.TestSpiController

ClassLoader:                                                                                                                                                                                                           
+-org.springframework.boot.loader.launch.LaunchedClassLoader@5305068a                                                                                                                                                  
  +-jdk.internal.loader.ClassLoaders$AppClassLoader@46fbb2c1                                                                                                                                                           
    +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@48b070d8                                                                                                                                                    

Location:                                                                                                                                                                                                              
nested:/opt/test-spi.jar/!BOOT-INF/classes/!/                                                                                                                                                                          

       /*
        * Decompiled with CFR.
        * 
        * Could not load the following classes:
        *  org.springframework.web.bind.annotation.GetMapping
        *  org.springframework.web.bind.annotation.RequestMapping
        *  org.springframework.web.bind.annotation.RestController
        */
       package com.logicfeng.testspi.controller;
       
       import org.springframework.web.bind.annotation.GetMapping;
       import org.springframework.web.bind.annotation.RequestMapping;
       import org.springframework.web.bind.annotation.RestController;
       
       @RestController
       @RequestMapping(value={"/test/spi"})
       public class TestSpiController {
           @GetMapping(value={"/name"})
           public String testSpi() {
/*20*/         String string = "lisi";
/*21*/         return string;
           }
       }

Affect(row-cnt:1) cost in 70 ms.

  • 测试
[root@logicfeng ~]# curl http://localhost:8032/test/spi/name
zhangsan[root@logicfeng ~]# curl http://localhost:8032/test/spi/name
[root@logicfeng ~]# curl http://localhost:8032/test/spi/name
lisi[root@logicfeng ~]# 

3 注意事项

  • 1、程序重启之后,字节码文件会恢复,除非将class文件放入jar包中进行更新。
  • 2、使用retransform不能添加方法或者字段!
  • 3、不能更新正在执行中的方法!
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逻辑峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值