java arthas redefine实现热替换某个类

简单的看下arthas redefine类的效果, 需要注意

  1. redefine 的 class 不能修改、添加、删除类的 field 和 method,包括方法参数、方法名称及返回值。
  2. redefine 后的原来的类不能恢复,redefine 有可能失败(比如增加了新的 field),参考 jdk 本身的文档。
  3. redefine命令和jad/watch/trace/monitor/tt等命令会冲突。执行完redefine之后,如果再执行上面提到的命令,则会把redefine的字节码重置。 原因是 jdk 本身 redefine 和 Retransform 是不同的机制,同时使用两种机制来更新字节码,只有最后修改的会生效。

前几天发现了一个巨牛的人工智能学习网站,通俗易懂,分享一下,可点击跳转


可以按照如下需要实践一下

  • 保持主程序运行
import java.util.concurrent.TimeUnit;

class AMain {

    public static void main(String[] args) {
        A a = new A();
        while(true) {
            a.say();
            try{
                TimeUnit.SECONDS.sleep(10);
            }catch (Exception e){

            }
        }
    }

}
  • A.java
public class A {
    public void say(){
        System.out.println("A1");
    }
}

修改A然后javac A生成新的A.class文件

  • arthas redefine
sc -d A
redefine -c 251a69d7 /Users/dwl/projects/javatmp/src/A.class

java arthas redefine实现热替换某个类_第1张图片

结果,程序一直保证运行,当arthas redifine后,程序输出新class的内容

同时可以将命令固化为shell执行脚本,如下

#!/bin/bash

# 配置参数
ARTHAS_JAR="arthas-boot.jar"
TARGET_CLASS="A"
CLASS_FILE="/Users/dwl/projects/javatmp/src/A.class"
OUT_FILE="/Users/dwl/projects/javatmp/redifine/outfile"
ehco '' >> $OUT_FILE

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

cd /Users/dwl
echo -e "${GREEN}开始Arthas自动化redefine流程...${NC}"

# 动态获取 PID
TARGET_PID=$(ps aux | grep "[j]ava" | grep "AMain" | awk '{print $2}')
if [ -z "$TARGET_PID" ]; then
    echo "找不到 AMain 进程"
    exit 1
fi

# 步骤1: 获取ClassLoader信息
echo -e "${YELLOW}步骤1: 获取ClassLoader信息...${NC}"

# 直接使用PID启动Arthas
echo -e "${YELLOW}正在获取ClassLoader信息...${NC}"
sc_command="sc -d ${TARGET_CLASS}\nquit"
echo -e ${sc_command} | java -jar "$ARTHAS_JAR" "$TARGET_PID" 2>&1 | tee "$OUT_FILE"
echo "ClassLoader信息已保存到: $OUT_FILE"

# 从文件中提取ClassLoader Hash
CLASSLOADER_HASH=$(grep "classLoaderHash" "$OUT_FILE" | tr -s ' ' | awk '{print $3}' | head -1)

if [ -z "$CLASSLOADER_HASH" ]; then
    echo -e "${RED}❌ 无法获取ClassLoader Hash${NC}"
    echo "请检查输出文件: $OUT_FILE"
    rm -rf "$TEMP_DIR"
    exit 1
fi

echo -e "${GREEN}✅ 获取到ClassLoader Hash: $CLASSLOADER_HASH${NC}"

# 步骤2: 执行redefine
echo -e "${YELLOW}步骤2: 执行redefine操作...${NC}"
redefine_command="redefine -c ${CLASSLOADER_HASH} ${CLASS_FILE}\nquit"
echo -e ${redefine_command} | java -jar "$ARTHAS_JAR" "$TARGET_PID" 2>&1 | tee -a "$OUT_FILE"

# 检查redefine结果
if grep -q "redefine success" "$OUT_FILE"; then
    echo -e "${GREEN}✅ Redefine成功!${NC}"
else
    echo -e "${RED}❌ Redefine失败!${NC}"
fi

你可能感兴趣的:(#,java类加载和gc,java,arthas)