• arthas在线改代码


    一、背景
    很久之前就有一个想法:如果部署在线上的代码在遇到类似空指针异常时能自动修复就好了。前段时间准备尝试落实这个想法。那就先从基础做起:先在线改代码吧!

    本来我是在学习字节码的,偶尔搜了一下资料,发现Arthas这个工具,能够实现代码热修改。

    我仿佛发现了新大陆,于是添加收藏。这时我发现,我的收藏夹里很早就收藏了这个网页。看来有些路终究是要走的。

    废话不说,试试吧!
    二、开始
    1、启动springboot项目
    2、运行arthas,并选择目标进程
    我这里选择2

    java -jar arthas-boot.jar
    [INFO] arthas-boot version: 3.6.0
    [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.

    • [1]: 6784 org.jetbrains.jps.cmdline.Launcher
      [2]: 6787 com.shuimutong.learn.arthos.helloweb.HelloWebApplication

    3、使用sc命令查找要修改的类
    我这里准备在StringUtil里加上一个打印,输入查找命令如下:

    [arthas@6787]$ sc -d *util.StringUtil
    
    • 1

    class-info com.shuimutong.learn.arthos.helloweb.util.StringUtil
    code-source /Users/zhengxingao/Documents/develop/arthoslearn/helloweb/target/classes/
    name com.shuimutong.learn.arthos.helloweb.util.StringUtil
    isInterface false
    isAnnotation false
    isEnum false
    isAnonymousClass false
    isArray false
    isLocalClass false
    isMemberClass false
    isPrimitive false
    isSynthetic false
    simple-name StringUtil
    modifier public
    annotation
    interfaces
    super-class ±java.lang.Object
    class-loader ±sun.misc.Launcher A p p C l a s s L o a d e r @ 18 b 4 a a c 2 + − s u n . m i s c . L a u n c h e r AppClassLoader@18b4aac2 +-sun.misc.Launcher AppClassLoader@18b4aac2+sun.misc.LauncherExtClassLoader@32a1bec0
    classLoaderHash 18b4aac2

    4、使用jad命令反编译出源码

    jad --source com.shuimutong.learn.arthos.helloweb.util.StringUtil > /tmp/StringUtil.java
    
    • 1

    输出目录建议选择/tmp,不用担心没有权限

    5、编辑/tmp/StringUtil.java
    arthas里面没法使用vi,所以新开窗口编辑吧。

    复制代码
    /*
    * Decompiled with CFR.
    */
    package com.shuimutong.learn.arthos.helloweb.util;

       public class StringUtil {
           public static String packHello(String name) {
               System.out.println("name:"+name);
    
    • 1
    • 2
    • 3

    /* 5*/ return String.format(“Hello %s!”, name);
    }
    }
    复制代码
    我加了个打印。

    6、编译文件

    mc -c 18b4aac2 /tmp/StringUtil.java -d /tmp
    
    • 1

    Memory compiler output:
    /tmp/com/shuimutong/learn/arthos/helloweb/util/StringUtil.class
    Affect(row-cnt:1) cost in 194 ms.

    -c后面跟的一串是字符是前面查找类时打印出的classLoadHash

    7、加载编译的class

    [arthas@6787]$ redefine /tmp/com/shuimutong/learn/arthos/helloweb/util/StringUtil.class
    
    • 1

    redefine success, size: 1, classes:
    com.shuimutong.learn.arthos.helloweb.util.StringUtil

    8、检验
    请求:http://localhost:8081/hello1?name=arthas

    控制台打印:name:arthas

    符合预期。

    热更新注意事项
    redefine 特别说明
    redefine 命令和 jad/watch/trace/monitor/tt 等命令会冲突。

    执行完 redefine 之后,如果再执行上面提到的命令,则会把 redefine 的字节码重置。

    原因是 jdk 本身 redefine 和 Retransform 是不同的机制,同时使用两种机制来更新字节码,只有最后修改的会生效。

    条件限制
    使用热更新功能有一些条件限制,我们只能用它来修改方法内部的一些业务代码,如果我们出现了以下任意一种情况,那么热更新就会执行失败:

    增加类属性(类字段);
    增加或删除方法;
    替换正在运行的方法。

  • 相关阅读:
    聚醋酸乙烯酯接枝聚苯乙烯PVAc-g-PSt微球/接枝-聚甲基丙烯酸甲酯表面(PS-acyl-Cl)的研究
    (附源码)spring boot教学管理平台 毕业设计 281454
    微信机器人开发
    创建一个pod,但pod的status持续:ContainerCreating
    盘盘在项目中你常用的那些数组API
    把请求头信息添加到请求报文中,然后发送请求到淘宝,显示回复信息
    Redis-企业级解决方案
    1、Pytorch初见
    关于组织开展2022年南京市创新产品(第一批)申报工作的通知
    mysql case when 不命中缓存
  • 原文地址:https://blog.csdn.net/mynameisjinxiaokai/article/details/128202972