redefine
加载外部的.class文件,redefine jvm已加载的类,结合jad/mc命令使用
推荐使用retransform命令
命令选项
命令选项 | 描述 |
---|---|
-c, --classloader <hash> | 指定ClassLoader的哈希值 |
--classLoaderClass <class-name> | 指定ClassLoader的类名 |
-h, --help | 帮助 |
<classFilePaths> | class文件路径 |
示例
修改MathGame代码如下
java
public void run() throws InterruptedException {
System.out.println("I'm running!");
try {
int number = random.nextInt()/10000;
List<Integer> primeFactors = primeFactors(number);
print(number, primeFactors);
} catch (Exception e) {
System.out.println(String.format("illegalArgumentCount:%3d, ", illegalArgumentCount) + e.getMessage());
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
bash
# 编译修改后的java文件
[arthas@13728]$ mc -d /tmp /tmp/MathGame.java
Memory compiler output:
C:\tmp\demo\MathGame.class
Affect(row-cnt:1) cost in 50 ms.
# 重定义class文件
[arthas@13728]$ redefine /tmp/demo/MathGame.class
redefine success, size: 1, classes:
demo.MathGame
# 定义后MathGame控制台输出如下
I'm running!
illegalArgumentCount:933, number is: -49676, need >= 2
I'm running!
illegalArgumentCount:934, number is: -58381, need >= 2
I'm running!
illegalArgumentCount:935, number is: -42343, need >= 2
I'm running!
illegalArgumentCount:936, number is: -14142, need >= 2
I'm running!
118346=2*47*1259
I'm running!
113905=5*11*19*109
I'm running!
illegalArgumentCount:937, number is: -128405, need >= 2
I'm running!
illegalArgumentCount:938, number is: -176102, need >= 2
I'm running!
illegalArgumentCount:939, number is: -36171, need >= 2
I'm running!
165054=2*3*27509
I'm running!
# 使用trace命令后 class文件还原
trace demo.MathGame run
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 29 ms, listenerId: 6
`---ts=2023-03-30 14:21:03;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@6d06d69c
`---[2.6848ms] demo.MathGame:run()
`---[39.61% 1.0634ms ] demo.MathGame:primeFactors() #25 [throws Exception]
# 还原源class文件
redefine /tmp/demo/MathGame.class
redefine success, size: 1, classes:
demo.MathGame
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
注意
- redefine后的类不能恢复,
reset
命令对redefine后的类无效,需要redefine原始的字节码- redefine可能失败,比如增加了新的字段、方法
- 正在运行的函数在函数没结束之前不会生效,比如MathGame中main方法的循环部分
- redefine命令和
jad
/watch
/trace
/monitor
/tt
等命令会冲突。执行完redefine后,再执行前面的命令会把redefine的字节码重置- 建议在redefine之前先dump源class文件备份 {: .block-danger }n